首页 文章

Visual C 2010,rvalue参考错误?

提问于
浏览
4

它是Visual C 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
}

我想,函数f(T &&)永远不应该被调用,但是用T = int&调用它 . 输出:

main.cpp(10): error C2338: no way
          main.cpp(17) : see reference to function template instantiation 'T f(T)' being compiled
          with
          [
              T=int &
          ]

Update 1 您知道任何C x0编译器作为参考吗?我已经尝试了在线测试驱动但无法编译r值参考 .

Update 2 解决方法(使用SFINAE):

#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.
}

Update 3 即使没有函数模板实例化,一些编译器也会触发static_assert(false,"no way") . 解决方法(感谢@Johannes Schaub - litb)

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");

2 回答

  • 3

    据我了解(我可能不完全正确;规范有点复杂),模板类型扣除规则对你不利 .

    编译器首先尝试替换所有模板(此时尚未选择 - 仅查找选项)并获取:

    • T const &rint 左侧与 T = int 匹配,创建 f(int const &)

    • T &&r 匹配 int 左值与 T = int&int & && 缩减为 int& ,创建 f(int &) (在spec中有规则说明这一点) .

    现在谈到选择正确的重载,后者是更好的匹配,因为第一个不同于cv资格而后者没有 . 这也是为什么当你删除 const 时,你得到模糊的过载错误 - 重载最终完全相同 .

    广告 Update1gcc支持many of the C++0x features . 您可以从mingw获取本机Windows构建或使用cygwin .

    广告 Update2 :如果你真的需要rvalue和左值的单独重载,那似乎是唯一的选择 . 但是大多数模板只使用任何类型的引用做正确的事情,可能使用 std::forward 来确保它们调用的函数的正确解析,这取决于它们是否具有rvalue或lvalue .

  • 5

    虽然您的修复无法解决 static_assert 问题 . static_assert(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;
    }
    

相关问题