Поскольку любой полученный результат зависит от параметра шаблона, необходимо typedef typename
.
decltype
- это стандартная функция C ++ 11. Это «оператор», который принимает выражение и возвращает тип.
typedef typename decltype( T().toCPD() ) D; // can't use T:: as it's nonstatic
Если T()
не является допустимым (T
не конструируемый по умолчанию), вам понадобится declval
, которая является функцией, которая принимает тип и возвращает бессмысленное, недопустимое значение этого типа. declval
может использоваться только в неоцененных контекстах, таких как decltype
.
typedef typename decltype( std::declval<T>().toCPD() ) D;
До C ++ 11 decltype
был нестандартным расширением компилятором Microsoft MSVC. Его поведение могло быть слегка изменено стандартизацией.
typeof
- это эквивалентное расширение GCC до C ++ 11, подобное decltype
, которое также было клонировано в других компиляторах. Здесь - это документация GCC. На этой странице нет сравнения между функциями, но отмечается, что typeof
должен называться __typeof__
при использовании стандартного режима (-std=c++YY
, который вы должны всегда делать), и он доступен в C, а также C ++.
Ради совместимости с C __typeof__
не разрешает ссылочный тип из выражения glvalue. Таким образом, он действительно подходит только для C. Это, вероятно, объясняет, почему функция C ++ не унаследовала более понятное имя: GNU не хотела жертвовать обратной совместимостью, тогда как Microsoft меньше заботится о C и, возможно, нуждалась в меньшем количестве изменений.
result_of
- это метафункция C ++ 11 (ранее стандартизированная в библиотеке ISO TR1 с 2006 года). Это шаблон, который принимает вызываемый тип (такой как функция int(void)
, указатель функции int(*)(void)
, класс функторов, реализующий operator()
или указатель на член-функцию &T::toCPD
) и список типов аргументов для этот тип и предоставляет тип возврата, если вызов будет работать.
Чтобы использовать result_of
с указателем на функцию-член, вы должны включить тип родительского объекта в список аргументов в качестве суррогата для this
.
typedef typename std::result_of< decltype( & T::toCPD ) ( T * ) >::type D;
Это очень хрупко, потому что &T::toCPD
не может быть разрешено, если есть какая-либо перегрузка, такая как неконстантная версия. Это верно, несмотря на то, что T *
или T const *
должны быть явно записаны! В большинстве случаев вам лучше использовать decltype
и declval
.