Reputation: 147
I see some code examples where the type used to instantiate the std::declval
template function is specified as a reference type rather than just a type, as in:
std::declval<T &>()
as opposed to:
std::declval<T>()
where T
is some type. I am missing the subtlety why the reference notation might be chosen overe the plain type. Would someone please explain this to me ?
I know that std::declval
expands to typename std::add_rvalue_reference<T>::type
but I am still missing the reason why one would instantiate the latter with a reference to a type rather than the plain type itself.
Upvotes: 7
Views: 822
Reputation: 28416
Due to reference collapsing the result is different (see the answer I linked in a comment), and it does have consequences.
Think of the fact that memeber functions can be &&
/&
/const&
qualified, for instance.
The following is a simple, even though probably meaningless, example of how passing T
vs T&
to std::declval
can have a "drastic" effect.
#include <type_traits>
struct A{};
struct B{};
struct C {
A f() && { return A{}; }
B f() const & { return B{}; }
};
int main() {
static_assert(std::is_same_v<A, decltype(std::declval<C>().f())>);
static_assert(std::is_same_v<B, decltype(std::declval<C&>().f())>);
}
Upvotes: 5