5

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.

Enlico
  • 23,259
  • 6
  • 48
  • 102
  • Does this answer your question? [Is there a reason declval returns add\_rvalue\_reference instead of add\_lvalue\_reference](https://stackoverflow.com/questions/20303250/is-there-a-reason-declval-returns-add-rvalue-reference-instead-of-add-lvalue-ref) – Enlico Apr 28 '21 at 20:23
  • No. Enrico, that has nothing to do with my question. – Edward Diener Apr 29 '21 at 02:31
  • what about my answer? – Enlico Apr 29 '21 at 04:42

1 Answers1

4

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())>);
}
Enlico
  • 23,259
  • 6
  • 48
  • 102