9.10. The "sizeof trick"Although values used as function arguments pass into the runtime world permanently, it is possible to get some information at compile time about the result type of a function call by using the sizeof operator. This technique has been the basis of numerous low-level template metafunctions, including many components of the Boost Type Traits library. For example, given: typedef char yes; // sizeof(yes) == 1 typedef char (&no)[2]; // sizeof(no) == 2 we can write a trait separating classes and unions from other types, as follows: template <class T> struct is_class_or_union { // SFINAE eliminates this when the type of arg is invalid template <class U> static yes tester(int U::*arg); // overload resolution prefers anything at all over "..." template <class U> static no tester(...); // see which overload is chosen when U == T static bool const value = sizeof(tester<T>(0)) == sizeof(yes); typedef mpl::bool_<value> type; }; struct X{}; BOOST_STATIC_ASSERT(is_class_or_union<X>::value); BOOST_STATIC_ASSERT(!is_class_or_union<int>::value); This particular combination of SFINAE with the sizeof TRick was first discovered by Paul Mensonides in March 2002. It's a shame that in standard C++ we can only pull the size of an expression's type, but not the type itself, back from runtime. For example, it would be nice to be able to write:
// generalized addition function object
struct add
{
template <class T, class U>
typeof(T+U) operator()(T const& t, U const& u)
{
return t+u;
}
};
Though it's not in the standard, many compilers already include a typeof operator (sometimes with one of the reserved spellings "__typeof" or "__typeof__"), and the C++ committee is very seriously discussing how to add this capability to the standard language. The feature is so useful that over the years several library-only implementations of typeof have been developed, all of which ultimately rely on the more limited capabilities of sizeof [Dew02]. The library implementations aren't fully automatic: User-defined types must be manually associated with unique numbers, usually through specializations of some traits class. You can find code and tests for one such library by Arkadiy Vertleyb in the pre-release materials on this book's companion CD. |