⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 type_traits.qbk

📁 C++的一个好库。。。现在很流行
💻 QBK
📖 第 1 页 / 共 5 页
字号:

Now, this "pair" cannot hold references as it currently stands, because the 
constructor would require taking a reference to a reference, which is 
currently illegal [link background.references \[7\]]. Let us consider what the constructor's parameters 
would have to be in order to allow "pair" to hold non-reference types, 
references, and constant references:

[table Required Constructor Argument Types
[[Type of `T1`] [Type of parameter to initializing constructor]]
[[T] [const T &]]
[[T &] [T &]]
[[const T &] [const T &]]
]

A little familiarity with the type traits classes allows us to construct a 
single mapping that allows us to determine the type of parameter from the 
type of the contained class. The type traits classes provide a 
transformation __add_reference, which adds a reference to its type, 
unless it is already a reference.

[table Using add_reference to synthesize the correct constructor type
[[Type of `T1`] [Type of `const T1`] [Type of `add_reference<const T1>::type`]]
[[T] [const T] [const T &]]
[[T &] [T & \[8\]] [T &]]
[[const T &] [const T &] [const T &]]
]
 
This allows us to build a primary template definition for `pair` that can 
contain non-reference types, reference types, and constant reference types:

   template <typename T1, typename T2> 
   struct pair 
   {
   typedef T1 first_type;
   typedef T2 second_type;

   T1 first;
   T2 second;

   pair(boost::__add_reference<const T1>::type nfirst,
         boost::__add_reference<const T2>::type nsecond)
   :first(nfirst), second(nsecond) { }
   };

Add back in the standard comparison operators, default constructor, 
and template copy constructor (which are all the same), and you have a 
`std::pair` that can hold reference types!

This same extension could have been done using partial template specialization 
of `pair`, but to specialize `pair` in this way would require three partial 
specializations, plus the primary template. Type traits allows us to 
define a single primary template that adjusts itself auto-magically to 
any of these partial specializations, instead of a brute-force partial 
specialization approach. Using type traits in this fashion allows 
programmers to delegate partial specialization to the type traits classes, 
resulting in code that is easier to maintain and easier to understand.

[h4 Conclusion]

We hope that in this article we have been able to give you some idea of 
what type-traits are all about. A more complete listing of the available 
classes are in the boost documentation, along with further examples using 
type traits. Templates have enabled C++ uses to take the advantage of the 
code reuse that generic programming brings; hopefully this article has 
shown that generic programming does not have to sink to the lowest common 
denominator, and that templates can be optimal as well as generic.

[h4 Acknowledgements]

The authors would like to thank Beman Dawes and Howard Hinnant for their 
helpful comments when preparing this article.

[h4 References]

# Nathan C. Myers, C++ Report, June 1995. 
# The type traits library is based upon contributions by Steve Cleary, Beman Dawes, Howard Hinnant and John Maddock: it can be found at www.boost.org. 
# A scalar type is an arithmetic type (i.e. a built-in integer or floating point type), an enumeration type, a pointer, a pointer to member, or a const- or volatile-qualified version of one of these types. 
# This quote is from Donald Knuth, ACM Computing Surveys, December 1974, pg 268. 
# The test code is available as part of the boost utility library (see algo_opt_examples.cpp), the code was compiled with gcc 2.95 with all optimisations turned on, tests were conducted on a 400MHz Pentium II machine running Microsoft Windows 98. 
# John Maddock and Howard Hinnant have submitted a "compressed_pair" library to Boost, which uses a technique similar to the one described here to hold references. Their pair also uses type traits to determine if any of the types are empty, and will derive instead of contain to conserve space -- hence the name "compressed". 
# This is actually an issue with the C++ Core Language Working Group (issue #106), submitted by Bjarne Stroustrup. The tentative resolution is to allow a "reference to a reference to T" to mean the same thing as a "reference to T", but only in template instantiation, in a method similar to multiple cv-qualifiers. 
# For those of you who are wondering why this shouldn't be const-qualified, remember that references are always implicitly constant (for example, you can't re-assign a reference). Remember also that "const T &" is something completely different. For this reason, cv-qualifiers on template type arguments that are references are ignored.

[endsect]

[section:category Type Traits by Category]
[section:value_traits Type Traits that Describe the Properties of a Type]

These traits are all /value traits/, which is to say the traits classes all
inherit from __integral_constant, and are used to access some numerical
property of a type.  Often this is a simple true or false Boolean value, 
but in a few cases may be some other integer value (for example when dealing
with type alignments, or array bounds: see `__alignment_of`, `__rank` and `__extent`).

[section:primary Categorizing a Type]

These traits identify what "kind" of type some type `T` is.  These are split into
two groups: primary traits which are all mutually exclusive, and composite traits
that are compositions of one or more primary traits.

For any given type, exactly one primary type trait will inherit from
__true_type, and all the others will inherit from __false_type, in other
words these traits are mutually exclusive.
 
This means that `__is_integral<T>::value` and `__is_floating_point<T>::value` 
will only ever be true for built-in types; if you want to check for a 
user-defined class type that behaves "as if" it is an integral or floating point type, 
then use the `std::numeric_limits template` instead.

[*Synopsis:]

   template <class T>
   struct __is_array<T>;
     
   template <class T>
   struct __is_class<T>;
     
   template <class T>
   struct __is_enum<T>;
     
   template <class T>
   struct __is_floating_point<T>;
     
   template <class T>
   struct __is_function<T>;

   template <class T>
   struct __is_integral<T>;
     
   template <class T>
   struct __is_member_function_pointer<T>;
     
   template <class T>
   struct __is_member_object_pointer<T>;
     
   template <class T>
   struct __is_pointer<T>;
     
   template <class T>
   struct __is_reference<T>;
     
   template <class T>
   struct __is_union<T>;
     
   template <class T>
   struct __is_void<T>;
     
The following traits are made up of the union of one or more type
categorizations. A type may belong to more than one of these categories, 
in addition to one of the primary categories.

   template <class T>
   struct __is_arithmetic;
   
   template <class T>
   struct __is_compound;
   
   template <class T>
   struct __is_fundamental;
   
   template <class T>
   struct __is_member_pointer;
   
   template <class T>
   struct __is_object;
   
   template <class T>
   struct __is_scalar;
   
[endsect]

[section:properties General Type Properties]

The following templates describe the general properties of a type.

[*Synopsis:]

   template <class T>
   struct __alignment_of;

   template <class T>
   struct __has_nothrow_assign;

   template <class T>
   struct __has_nothrow_constructor;

   template <class T>
   struct __has_nothrow_copy;

   template <class T>
   struct __has_trivial_assign;

   template <class T>
   struct __has_trivial_constructor;

   template <class T>
   struct __has_trivial_copy;

   template <class T>
   struct __has_trivial_destructor;

   template <class T>
   struct __has_virtual_destructor;

   template <class T>
   struct __is_abstract;

   template <class T>
   struct __is_const;

   template <class T>
   struct __is_empty;

   template <class T>
   struct __is_stateless;

   template <class T>
   struct __is_pod;

   template <class T>
   struct __is_polymorphic;

   template <class T>
   struct __is_volatile;

   template <class T, std::size_t N = 0>
   struct __extent;

   template <class T>
   struct __rank;

[endsect]

[section:relate Relationships Between Two Types]

These templates determine the whether there is a relationship 
between two types:

[*Synopsis:]

   template <class Base, class Derived>
   struct __is_base_of;

   template <class From, class To>
   struct __is_convertible;

   template <class T, class U>
   struct __is_same;
   
[endsect]

[endsect]
[section:transform Type Traits that Transform One Type to Another]

The following templates transform one type to another, 
based upon some well-defined rule. 
Each template has a single member called `type` that is the 
result of applying the transformation to the template argument `T`.

[*Synopsis:]

   template <class T>
   struct __add_const;

   template <class T>
   struct __add_cv;
   
   template <class T>
   struct __add_pointer;

   template <class T>
   struct __add_reference;

   template <class T>
   struct __add_volatile;

   template <class T>
   struct __remove_all_extents;

   template <class T>
   struct __remove_const;

   template <class T>
   struct __remove_cv;

   template <class T>
   struct __remove_extent;

   template <class T>
   struct __remove_pointer;

   template <class T>
   struct __remove_reference;

   template <class T>
   struct __remove_volatile;

[h4 Broken Compiler Workarounds:]

For all of these templates support for partial specialization of class templates is 
required to correctly implement the transformation. 
On the other hand, practice shows that many of the templates from this 
category are very useful, and often essential for implementing some 
generic libraries. Lack of these templates is often one of the major 
limiting factors in porting those libraries to compilers that do not yet 
support this language feature. As some of these compilers are going to be 
around for a while, and at least one of them is very wide-spread, 
it was decided that the library should provide workarounds where possible. 

The basic idea behind the workaround is to manually define full 
specializations of all type transformation templates for all fundamental types, 
and all their 1st and 2nd rank cv-[un]qualified derivative pointer types, and to 
provide a user-level macro that will define all the explicit specializations needed 
for any user-defined type T. 

The first part guarantees the successful compilation of something like this:

   BOOST_STATIC_ASSERT((is_same<char, remove_reference<char&>::type>::value));
   BOOST_STATIC_ASSERT((is_same<char const, remove_reference<char const&>::type>::value));
   BOOST_STATIC_ASSERT((is_same<char volatile, remove_reference<char volatile&>::type>::value));
   BOOST_STATIC_ASSERT((is_same<char const volatile, remove_reference<char const volatile&>::type>::value));
   BOOST_STATIC_ASSERT((is_same<char*, remove_reference<char*&>::type>::value));
   BOOST_STATIC_ASSERT((is_same<char const*, remove_reference<char const*&>::type>::value));
   ...
   BOOST_STATIC_ASSERT((is_same<char const volatile* const volatile* const volatile, remove_reference<char const volatile* const volatile* const volatile&>::type>::value));
   
and the second part provides the library's users with a mechanism to make the 
above code work not only for `char`, `int` or other built-in type, 
but for they own types as well:

   namespace myspace{
      struct MyClass {};
   }
   // declare this at global scope:
   BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(myspace::MyClass)
   // transformations on myspace::MyClass now work:
   BOOST_STATIC_ASSERT((is_same<myspace::MyClass, remove_reference<myspace::MyClass&>::type>::value));
   BOOST_STATIC_ASSERT((is_same<myspace::MyClass, remove_const<myspace::MyClass const>::type>::value));
   // etc.
   
Note that the macro BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION evaluates 
to nothing on those compilers that *do* support partial specialization.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -