Difference between revisions of "cpp/utility/declval"
From cppreference.com
m |
(→Possible implementation: simplify per CWG 2518) |
||
(24 intermediate revisions by 13 users not shown) | |||
Line 2: | Line 2: | ||
{{cpp/utility/navbar}} | {{cpp/utility/navbar}} | ||
{{dcl begin}} | {{dcl begin}} | ||
− | {{dcl header | utility}} | + | {{dcl header|utility}} |
− | {{dcl | since=c++11 | | + | {{dcl|since=c++11| |
template< class T > | template< class T > | ||
− | typename std::add_rvalue_reference<T>::type declval(); | + | typename std::add_rvalue_reference<T>::type declval() noexcept; |
}} | }} | ||
{{dcl end}} | {{dcl end}} | ||
− | Converts any type {{tt|T}} to a reference type, making it possible to use member functions in {{ | + | Converts any type {{tt|T}} to a reference type, making it possible to use member functions in the operand of the [[cpp/language/decltype|{{tt|decltype}} specifier]] without the need to go through constructors. |
− | {{tt|declval}} is commonly used in templates where acceptable template parameters may have no constructor in common, but have the same member function whose return type is needed. Note that | + | {{tt|std::declval}} is commonly used in templates where acceptable template parameters may have no constructor in common, but have the same member function whose return type is needed. |
+ | |||
+ | Note that {{tt|std::declval}} can only be used in [[cpp/language/expressions#Potentially-evaluated expressions|unevaluated contexts]] and is not required to be defined; it is an error to evaluate an expression that contains this function. Formally, the program is ill-formed if this function is [[cpp/language/definition#ODR-use|odr-used]]. | ||
===Parameters=== | ===Parameters=== | ||
Line 17: | Line 19: | ||
===Return value=== | ===Return value=== | ||
− | Cannot be called and thus never returns a value. The return type is {{tt|T&&}} unless {{tt|T}} is (possibly cv-qualified) {{ | + | Cannot be called and thus never returns a value. The return type is {{tt|T&&}} unless {{tt|T}} is (possibly cv-qualified) {{c/core|void}}, in which case the return type is {{tt|T}}.<!--Note that reference collapsing may take place when determine what T&& refers to.--> |
− | === | + | ===Possible implementation=== |
− | {{noexcept}} | + | {{eq fun |
+ | |1= | ||
+ | template<typename T> | ||
+ | typename std::add_rvalue_reference<T>::type declval() noexcept | ||
+ | { | ||
+ | static_assert(false, "declval not allowed in an evaluated context"); | ||
+ | } | ||
+ | }} | ||
===Example=== | ===Example=== | ||
{{example | {{example | ||
− | + | |code= | |
− | + | ||
− | + | ||
#include <iostream> | #include <iostream> | ||
+ | #include <utility> | ||
− | struct Default { | + | struct Default |
− | int foo() const {return 1;} | + | { |
+ | int foo() const { return 1; } | ||
}; | }; | ||
− | struct NonDefault { | + | struct NonDefault |
− | NonDefault( | + | { |
− | int foo() const {return 1;} | + | NonDefault() = delete; |
+ | int foo() const { return 1; } | ||
}; | }; | ||
int main() | int main() | ||
{ | { | ||
− | decltype(Default().foo()) n1 = 1; // | + | decltype(Default().foo()) n1 = 1; // type of n1 is int |
− | // decltype(NonDefault().foo()) n2 = n1; // error: no default constructor | + | // decltype(NonDefault().foo()) n2 = n1; // error: no default constructor |
− | decltype(std::declval<NonDefault>().foo()) n2 = n1; // | + | decltype(std::declval<NonDefault>().foo()) n2 = n1; // type of n2 is int |
− | std::cout << "n2 = " << n2 << '\n'; | + | std::cout << "n1 = " << n1 << '\n' |
+ | << "n2 = " << n2 << '\n'; | ||
} | } | ||
− | + | |output= | |
+ | n1 = 1 | ||
n2 = 1 | n2 = 1 | ||
}} | }} | ||
Line 51: | Line 63: | ||
===See also=== | ===See also=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc inc | cpp/language/dsc decltype}} | + | {{dsc inc|cpp/language/dsc decltype}} |
− | {{dsc inc | cpp/types/dsc result_of}} | + | {{dsc inc|cpp/types/dsc result_of}} |
{{dsc end}} | {{dsc end}} | ||
− | + | {{langlinks|de|es|fr|it|ja|pt|ru|zh}} | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + |
Latest revision as of 13:44, 21 September 2023
Defined in header <utility>
|
||
template< class T > typename std::add_rvalue_reference<T>::type declval() noexcept; |
(since C++11) | |
Converts any type T
to a reference type, making it possible to use member functions in the operand of the decltype
specifier without the need to go through constructors.
std::declval
is commonly used in templates where acceptable template parameters may have no constructor in common, but have the same member function whose return type is needed.
Note that std::declval
can only be used in unevaluated contexts and is not required to be defined; it is an error to evaluate an expression that contains this function. Formally, the program is ill-formed if this function is odr-used.
Contents |
[edit] Parameters
(none)
[edit] Return value
Cannot be called and thus never returns a value. The return type is T&&
unless T
is (possibly cv-qualified) void, in which case the return type is T
.
[edit] Possible implementation
template<typename T> typename std::add_rvalue_reference<T>::type declval() noexcept { static_assert(false, "declval not allowed in an evaluated context"); } |
[edit] Example
Run this code
#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; // type of n1 is int // decltype(NonDefault().foo()) n2 = n1; // error: no default constructor decltype(std::declval<NonDefault>().foo()) n2 = n1; // type of n2 is int std::cout << "n1 = " << n1 << '\n' << "n2 = " << n2 << '\n'; }
Output:
n1 = 1 n2 = 1
[edit] See also
decltype specifier(C++11)
|
obtains the type of an expression or an entity |
(C++11)(removed in C++20)(C++17) |
deduces the result type of invoking a callable object with a set of arguments (class template) |