decltype, result_of или typeof? - PullRequest
       10

decltype, result_of или typeof?

12 голосов
/ 04 мая 2010

у меня есть:

class A {
public:
    B           toCPD() const;

И

template<typename T>
class Ev {
public:
    typedef result_of(T::toCPD()) D;

После создания экземпляра Ev<A> компилятор говорит:

meta.h: 12: ошибка: 'T :: toCPD' не является типом

Ни decltype, ни typeof не работают.

Ответы [ 2 ]

32 голосов
/ 04 мая 2010

Поскольку любой полученный результат зависит от параметра шаблона, необходимо 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.

3 голосов
/ 04 мая 2010

result_of не является ни функцией, ни оператором.result_of - это мета-функция, имеющая функцию в качестве параметра template и устанавливающая тип результата для типа элемента

typedef typename result_of<T::toCPD()>::type D;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...