Home > Mobile >  Why decltype(auto) infers T& as return type, while dedicated T& does not?
Why decltype(auto) infers T& as return type, while dedicated T& does not?

Time:09-23

Consider this snippet:

#include <stdexcept>

template <typename T> class MyClass;

template <typename T> struct MyClass<T &> {

  constexpr T &foo() && {
    return value != nullptr ? std::move(*value)
                            : throw std::runtime_error("foo");
  }

  constexpr decltype(auto) bar() && {
    return value != nullptr ? std::move(*value)
                            : throw std::runtime_error("bar");
  }

  T *value;
};

int main() {
  const int &good = MyClass<int &>{}.bar();
  const int &bad = MyClass<int &>{}.foo();
}

Demo

Why is return specification decltype(auto) in method bar working, while T& in foo does not?

CodePudding user response:

Why decltype(auto) infers T& as return type

No, the return type of bar() is T&&, i.e. int&& in this case. For decltype:

if the value category of expression is xvalue, then decltype yields T&&;

std::move(*value) is an xvalue-expression, so the deduced return type is T&&.

On the other hand, the return type of foo is specified as T&, but std::move(*value) is an xvalue (rvalue) and can't be bound to T&, i.e. an lvalue-reference to non-const.

  • Related