visualc&x2B+;2010,右值参考错误? 是VisualC++ 2010中的错误还是正确的行为? template<class T> T f(T const &r) { return r; } template<class T> T f(T &&r) { static_assert(false, "no way"); //< line # 10 return r; } int main() { int y = 4; f(y); //< line # 17 }

visualc&x2B+;2010,右值参考错误? 是VisualC++ 2010中的错误还是正确的行为? template<class T> T f(T const &r) { return r; } template<class T> T f(T &&r) { static_assert(false, "no way"); //< line # 10 return r; } int main() { int y = 4; f(y); //< line # 17 },c++,visual-c++,c++11,visual-c++-2010,rvalue-reference,C++,Visual C++,C++11,Visual C++ 2010,Rvalue Reference,据我所知(我可能不完全正确;规范有点复杂),模板类型推断规则合谋反对您 编译器首先尝试替换所有模板(此时还没有选择,只是寻找选项),并得到: T const&r将int左值与T=int匹配,创建f(int const&) T&&r将int左值与T=int&匹配,并且int&&减少为int&,创建f(int&)(本手册中有这样的规则) 现在要选择正确的重载,后者更适合,因为前者的cv限定不同,后者则不相同。这也是为什么当您删除常量时,会出现不明确的重载错误,重载结果完全相同 Ad更新1:支持。

据我所知(我可能不完全正确;规范有点复杂),模板类型推断规则合谋反对您

编译器首先尝试替换所有模板(此时还没有选择,只是寻找选项),并得到:

  • T const&r
    int
    左值与
    T=int
    匹配,创建
    f(int const&)
  • T&&r
    int
    左值与
    T=int&
    匹配,并且
    int&&
    减少为
    int&
    ,创建
    f(int&)
    (本手册中有这样的规则)
现在要选择正确的重载,后者更适合,因为前者的cv限定不同,后者则不相同。这也是为什么当您删除
常量时,会出现不明确的重载错误,重载结果完全相同

Ad更新1:支持。您可以从或使用获取本机windows生成


AdUpdate2:如果您确实需要为右值和左值单独重载,那么这似乎是唯一的选择。但是大多数模板对任何类型的引用都是正确的,可能使用
std::forward
来确保它们调用的函数的正确解析,这取决于它们是右值还是左值)。

但是,您的修复并不能解决
静态断言
触发的问题。对于在定义时解析模板的编译器,
静态断言(false,…)
仍然会触发(大多数编译器都会)

他们将看到任何函数模板实例化都是格式错误的,标准允许他们为模板本身发出错误,大多数人都会这样做

为了实现这一点,您需要使表达式依赖,以便编译器不知道何时解析它将始终计算为false的模板。比如说

template<class> struct false_ { static bool const value = false; };

template<class T>
T f(T &&r)
{
    static_assert(false_<T>::value, "no way"); //< line # 10
    return r;
}
template struct false{static bool const value=false;};
模板
T f(T&r)
{
静态断言(假值,“不可能”)/
谢谢。SPEC的第14.2.2.1节描述了这个行为。vector::插入有相同的bug,它被固定在VS2013中:我想知道VisualC++的特性是不是总是被触发? StistalyAsStEt(false,…)< /C>?使用G++,断言必须是模板参数,除非函数被实例化,否则不触发,我认为它是VisualC++的“特性”。对于其他编译器,请使用“static_assert(sizeof(T)=sizeof(F),“no way”)。不合规性肯定不是一个特性。无论如何,
sizeof(T)==0
是一种使断言总是失败的好方法,但是要依赖于它。(我有一个
always_false::value
模板放在周围。)@GMan同意。我用引号写了“特写”。一种幽默。我补充了一个答案,指出了这一点。既然问题是为什么静态断言会触发,我认为最好有一个关于静态断言的答案。我同意静态断言需要对某些编译器进行修复。谢谢
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_reference.hpp>

template<class T>
T f(T &r)
{
    return r;
}

template<class T>
typename ::boost::disable_if< ::boost::is_reference<T>, T>::type f(T &&r)
{
    static_assert(false, "no way");
    return r;
}

int main()
{
    int y = 4;
    f(y);
    // f(5); // generates "no way" error, as expected.
}
template<class T> struct false_ { static bool const value = false; };
...
static_assert(false_<T>::value, "no way");
static_assert(sizeof(T) == sizeof(T), "no way");
template<class> struct false_ { static bool const value = false; };

template<class T>
T f(T &&r)
{
    static_assert(false_<T>::value, "no way"); //< line # 10
    return r;
}