为什么 decltype(auto) 将 T& 推断为 return 类型,而专用 T& 却不是?

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

考虑这个片段:

#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

为什么方法 bar 中的 return 规范 decltype(auto) 有效,而 foo 中的 T& 无效?

Why decltype(auto) infers T& as return type

不是,bar()的return类型是T&&,即本例中的int&&。对于 decltype:

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

std::move(*value) 是一个 xvalue 表达式,所以推导的 return 类型是 T&&.

另一方面,foo的return类型被指定为T&,但是std::move(*value)是一个xvalue(右值)并且不能被绑定到 T&,即对非常量的左值引用。