TR1 also introduces a set of traits that are used to determine how types are related to each other.
Quote:// [4.6] type relations:template struct is_same;template struct is_base_of;template struct is_convertible;
These are fairly self explanatory. The is_same trait will determine if U is exactly a T. is_base_of will determine if Derived is derived from Base either directly or indirectly. The is_convertable trait allows you to test if you can convert from one type to another type implicitly. The following asserts hold true for these three relational traits:
struct A {};struct B : A {};struct C : B {};struct D { operator int() { return 2; } };assert((is_same<int, int>::value));assert((!is_same<int, const int>::value));assert((!is_same<int, long>::value));assert((is_base_of::value));assert((is_base_of::value));assert((!is_base_of::value));assert((is_convertable<int, long>::value));assert((is_convertable::value));assert((!is_convertable::value));assert((is_convertableint
Type Modification
The final set of metafunctionality that I will discuss from TR1 is the ability to modify types.
Quote:// [4.7.1] const-volatile modifications:template struct remove_const;template struct remove_volatile;template struct remove_cv;template struct add_const;template struct add_volatile;template struct add_cv;// [4.7.2] reference modifications:template struct remove_reference;template struct add_reference;// [4.7.3] array modifications:template struct remove_extent;template struct remove_all_extents;// [4.7.4] pointer modifications:template struct remove_pointer;template struct add_pointer;
These are all fairly self explanatory. Plug in a Type in one end, get a different type (or the same type) out the other end. The two that I will discuss here are remove_extent and remove_all_extents. remove_extent will remove one dimension of an array. If the type is not an array, then it will not modify the type in any way. remove_all_extents works in the same way as remove_extent except that it will remove all dimensions of an array, resulting in the base type. The following asserts hold true for these two metafunctions:
assert((rankint
assert((is_sameint[][3]>::type, int[3]>::value));
assert((is_sameint[][3][4]>::type, int[3][4]>::value));
assert((rankint[][3][3]>::type>::value == 0));
assert((is_sameint[][3][3]>::type, int>::value));
As you can see from the asserts, remove_extent will remove the outermost dimension of the array.
Reader Exercises
Since Coder wanted me to add some exercises to my journal, I will give you two, post your answers as replies to this journal entry, or PM them to me. I will post the answers as a reply to this journal entry.
Exercise 1:
Build a recursive template, like that of remove_all_extents except that it will remove all pointers till it encounters a non-pointer type. For instance:
int ** would become int
Exercise 2:
Build a recursive template that will add a const qualifier to each rank of a pointer type. For instance:
int ** would become int const * const * const.
The following asserts should hold true for these exercises:
assert((is_sameint
assert((is_sameint ***>::type, int>::value));
assert((is_sameconst int>::type, const int>::value));
assert((is_sameint>::type, int>::value));
assert((is_sameint * const **>::type, int>::value));
assert((is_sameint* const *>::type, int const * const * const>::value));
assert((is_sameint*>::type, int const * const>::value));
assert((is_sameint**>::type, int const * const * const>::value));
assert((is_sameint>::type, const int>::value));