Professional C__ - Marc Gregoire [361]
Primary type categories is_void
is_integral
is_floating_point
is_pointer
. . .
Composited type categories is_reference
is_object
is_scalar
. . .
Type properties is_const
is_literal_type
is_polymorphic
is_unsigned
is_constructible
is_copy_constructible
is_move_constructible
is_assignable
. . .
Type relations is_same
is_base_of
is_convertible
const-volatile modifications remove_const
add_const
. . .
Reference modifications remove_reference
add_lvalue_reference
add_rvalue_reference
Sign modifications make_signed
make_unsigned
Other transformations enable_if
conditional
. . .
Type traits is a pretty advanced and complicated feature. By just looking at the preceding list, which is already a shortened version of the list in the standard itself, it is clear that this book cannot explain all details about type traits. This section explains just a couple of use cases to show you how type traits could be used.
Using Type Categories
Type traits requires the The standard defines an integral_constant class that looks as follows: template struct integral_constant { static constexpr T value = v; typedef T value_type; typedef integral_constant constexpr operator value_type() { return value; } }; typedef integral_constant typedef integral_constant What this defines is two types: true_type and false_type. When you call true_type::value you will get the value true and when you call false_type::value you will get the value false. You can also call true_type::type, which will return the type of true_type. The same holds for false_type. Classes like is_integral and is_class inherit from integral_constant. For example, is_integral can be specialized for type bool as follows: template<> struct is_integral This allows you to write is_integral The following code shows the simplest example of how type categories can be used: if (is_integral cout << "int is integral" << endl; } else { cout << "int is not integral" << endl; } if (is_class cout << "string is a class" << endl; } else { cout << "string is not a class" << endl; } Code snippet from TypeTraits\basic.cpp This example is using is_integral to check whether int is an integral type or not, and uses is_class to check whether string is a class or not. The output is as follows: int is integral string is a class Of course, you will likely never use type traits in this way. They become more useful in combination with templates to generate code based on some properties of a type. The following template example demonstrates this: template void process_helper(const T& t, true_type) { cout << t << " is an integral type." << endl; } template void process_helper(const T& t, false_type) { cout << t << " is a non-integral type." << endl; } template void process(const T& t) { process_helper(t, typename is_integral } int main() { process(123); process(2.2); process(string("Test")); return 0; } Code snippet from TypeTraits\is_integral.cpp The output of this example is as follows: 123 is an integral type. 2.2 is a non-integral type. Test is a non-integral type. The preceding code defines an overloaded function template process_helper() that accepts a type as template argument. The first argument to this function is a value and the second argument is