std::declval
| Определён в заголовке <utility>
|
||
template< class T >
typename std::add_rvalue_reference<T>::type declval() noexcept;
|
(начиная с C++11) (до C++14) (только невычисляемый) |
|
template< class T >
std::add_rvalue_reference_t<T> declval() noexcept;
|
(начиная с C++14) (только невычисляемый) |
|
Вспомогательный шаблон для написания выражений, которые появляются в невычисляемых контекстах, обычно в операнде decltype. В невычисляемом контексте этот вспомогательный шаблон преобразует любой тип T (который может быть неполным типом) в выражение этого типа, позволяя использовать функции-члены T без необходимости обращаться к конструкторам.
std::declval можно использовать только в невычисляемых контекстах и не обязательно должен быть определён; вычисление выражения, содержащего эту функцию, является ошибкой. Формально программа считается некорректной, если эта функция использована по правилу ODR.
Параметры
(нет)
Возвращаемое значение
Не может быть вычислено и, следовательно, никогда не возвращает значение. Возвращаемый тип —
T&&
(применяются правила схлопывания ссылок), за исключением случая, когда
T
является (возможно, cv-квалифицированным)
void
, в этом случае возвращаемый тип —
T
.
Примечания
std::declval
обычно используется в шаблонах, где допустимые параметры шаблона могут не иметь общего конструктора, но имеют одинаковую функцию-член, возвращаемый тип которой требуется получить.
Возможная реализация
template<typename T> typename std::add_rvalue_reference<T>::type declval() noexcept { static_assert(false, "declval not allowed in an evaluated context"); } |
Пример
#include <iostream> #include <utility> struct Default { int foo() const { return 1; } }; struct NonDefault { NonDefault() = delete; int foo() const { return 1; } }; int main() { decltype(Default().foo()) n1 = 1; // тип n1 - int decltype(std::declval<Default>().foo()) n2 = 1; // то же самое // decltype(NonDefault().foo()) n3 = n1; // ошибка: нет конструктора по умолчанию decltype(std::declval<NonDefault>().foo()) n3 = n1; // тип n3 - int std::cout << "n1 = " << n1 << '\n' << "n2 = " << n2 << '\n' << "n3 = " << n3 << '\n'; }
Вывод:
n1 = 1 n2 = 1 n3 = 1
Смотрите также
decltype
спецификатор
(C++11)
|
получает тип выражения или сущности |
|
(C++11)
(удалён в C++20)
(C++17)
|
выводит тип результата вызова вызываемого объекта с набором аргументов
(шаблон класса) |