user3882729
user3882729

Reputation: 1534

declval<T> vs declval<T&>

I'm trying to understand the difference between declval<T>() and declval<T&>()? Is there an example where T& can be used while T cannot?

#include <type_traits>
#include <utility>

struct X {
  X() = delete;
  int func();
};

int main()
{
// works with both X as well as X& within declval
  static_assert(std::is_same_v<decltype(std::declval<X&>().func()), int>);
}

Upvotes: 3

Views: 546

Answers (2)

rustyx
rustyx

Reputation: 85531

Apart from ref-qualified member functions (which are used rarely), a more common use-case for std::declval<T&>() is to create an lvalue reference (it creates an rvalue-reference otherwise).

#include <type_traits>
#include <utility>

struct X {};

int func(X&);

int main() {
  static_assert(std::is_same_v<decltype(func(std::declval<X&>())), int>); // works
  static_assert(std::is_same_v<decltype(func(std::declval<X>())), int>); // error
}

Upvotes: 5

Ted Lyngmo
Ted Lyngmo

Reputation: 117972

Is there an example where T& can be used while T cannot?

Yes, for example in situations like this where you have ref-qualified overloads:

struct X {
    X() = delete;
    int func() &;
    double func() &&;
};

int main() {
    // this static_assert would fail:
    static_assert(std::is_same_v<decltype(std::declval<X>().func()), int>);
}

Upvotes: 3

Related Questions