Интересное замечание здесь заключается в применении наших знаний от динамического полиморфизма к полиморфизму «функция типа».
Если сравнить эту функцию f:
struct I { virtual double f()const = 0; }; // C++ version of 'an interface'
struct A : public I { virtual double f()const{ return 0; } };
struct B : public I { virtual double f()const{ return 1; } };
struct C { };
void f( const I& i ){ return I.f(); }
f( A() );
f( C() ); // compiler warning: wrong type provided.
с этой функцией f:
// struct TI { typedef ??? iT; }; // no C++ version of a type-interface
struct TA { typedef int iT; };
struct TB { typedef double iT; };
struct TC { };
template< typename aTI > struct fT { typedef aTI::iT returnType; };
fT< TA >::returnType vA;
ft< C >::returnType vC; // compiler error: C has no iT member.
Вы видите, что единственная разница - это обозначения параметров. Первая функция - это «правильная» полиморфная функция. Компилятор предупредит нас, если предоставленный аргумент имеет неправильный тип.
fT - это функция, которая может использоваться только компилятором для определения определенного типа. Он принимает тип в качестве аргумента. Но у языка нет «концепции» ограничения типа (пока - см. Концепции в C ++ 0x). Поэтому нам нужно гарантировать, что типы, которые мы используем для функции типа, «реализуют» правильный интерфейс.
В конкретном случае это сводится к добавлению типа scalar_t
к любому классу, который вы хотите использовать с функцией типа numeric_type_traits_c
.