Является ли declval & lt; T & gt; () таким же, как (* (T *) nullptr)?

Является declval<T>() просто замена старой уловки (*(T*)NULL) получить экземпляр T в типе decl, не беспокоясь о конструкторе T?

Вот пример кода:

struct A {};

struct B {
A a;
};

typedef decltype((*(B*)nullptr).a) T1;
typedef decltype(declval<B>().a) T2;

cout << "is_same: " << is_same<T1, T2>::value << endl;

который печатает 1, потому что T1 и T2 одного типа.

Если declval — это больше, чем замена, каковы различия и где это полезно?

21

Решение

declval() имеет преимущество в том, что, если он используется в оцененном контексте (то есть используется odr), то программа плохо сформирована (20.2.4p2), и требуется диагностика (согласно 1.4p1). Как правило, это осуществляется через static_assert в библиотеке:

c++/4.7/type_traits: In instantiation of '[...] std::declval() [...]':
source.cpp:3:22:   required from here
c++/4.7/type_traits:1776:7: error: static assertion failed: declval() must not be used!

declval также работает на ссылочных типах:

using S = int &;
using T = decltype(std::declval<S>());
using U = decltype(*(S *)nullptr);  // fails

Где тип не ссылочный тип, declval даст тип значения где nullptr дает lvalue.

26

Другие решения

Нет, declval<T>() это не то же самое, что (*(T*)nullptr), А также decltype(expr.bar) это не то же самое, что decltype((expr.bar)),

Первое сравнение сравнивает выражения. Последнее использование decltype проверяет выражение и бывшее использование decltype проверяет заявленный тип expr.bar, Таким образом, вы должны сократить ваше использование decltype операнд, чтобы сделать полезное сравнение типов, и вы обнаружите, что они разные.

struct A {};

struct B {
A a;
};

// E1: B().a
// E2: declval<A>().a
// E3: (*(B*)0).a
// E4: ((B&&)(*(B*)0)).a

В этих 4 выражениях все выражения имеют тип A, E1 является prvalue (в C ++ 14 это xvalue. Некоторые компиляторы, вероятно, будут обрабатывать его как xvalue даже в режиме C ++ 11), E2 это xvalue. E3 это lvalue и E4 снова значение xvalue

// T1: decltype((*(B*)0).a)
// T2: decltype(((*(B*)0).a))

В этих двух типах первый decltype дает тип члена, названного выражением. Член имеет тип A, так T1 является A, Второй decltype возвращает тип выражения, измененный & если выражение является lvalue и изменено && если выражение является xvalue. Выражение является lvalue, поэтому T2 является A&,

7

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector