llx*_*xee 0 c++ templates sfinae c++11 c++17
我搜索了但确实找不到答案,为什么仅当参数由左值引用传递时才会发生 SFINAE,但当参数由右值引用传递时构建会成功:
template <typename T>
class A {
public:
using member_type = T;
};
template <typename AType>
typename AType::member_type f(AType&& m) {
typename AType::member_type res{};
return res;
}
void demo() {
A<int> a;
// ERROR: candidate template ignored: substitution failure
// [with AType = A<int> &]: type 'A<int> &'
// cannot be used prior to '::' because it has no members
f(a);
// BUILD SUCCESS
f(std::move(a));
}
Run Code Online (Sandbox Code Playgroud)
当你有
template <typename AType>
typename AType::member_type f(AType&& m)
Run Code Online (Sandbox Code Playgroud)
您拥有所谓的转发参考。尽管它看起来像右值引用,但此引用类型可以绑定到左值或右值。它的工作方式是,当您将左值传递给 时f,AType会被推导为 is T&,而当您传递右值时,AType会被推导为 just T。
因此,当您确实f(a); AType被推导为 时A<int>&,并且您尝试形成A<int>&::member_type无效的返回类型,因为引用没有类型成员。
相反,当您这样做时f(std::move(a));,AType会被推导为A<int>并且A<int>确实有一个member_type类型成员。
std::decay_t要解决此问题,您可以使用like删除类型的引用性
template <typename AType>
auto f(AType&& m) {
typename std::decay_t<AType>::member_type res{};
return res;
}
Run Code Online (Sandbox Code Playgroud)