模板函数类型推导和operator<<

14
当我使用MSVC++编译以下代码时,会出现错误:
struct A
{
    template<typename T>
    void operator<<(T&& x)
    {
    }

};
void f()
{
}
int main()
{
    A().operator<<( f );  // ok
    A() << f;             // error

    return 0;
}

g++clang都可以成功编译这段代码。据我所知,'ok'和'error'两行代码执行的是完全相同的操作,并且类型T被推导为void(&)()。或者是void()并且函数的右值引用是允许的吗?如果是这样的话,它们的含义是什么?像这样通过引用传递函数是可以的吗?'error'行无法在MSVC++中编译通过,这是一个错误吗?顺便说一下,错误输出:

no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)
could be 'void A::operator <<<void(void)>(T (__cdecl &&))'
with[ T=void (void) ]

1
你能提供你的C++编译器版本吗? - xis
已测试MSVC++2012带NOV CTP更新、gcc 4.5.3和4.7.2,以及clang 3.0和3.1。 - dsi
我没有VC11,所以很难进行调查,但这似乎是URef折叠的一个错误。编译器错误地将其解释为函数的RRef,并不接受输入中的lvalue。有趣的是检查 typedef void (* test)(); test g() { return f; } ... A() << g(); 是否可行。 - Andy Prowl
5
好的,我已经提交了一个错误报告 - dsi
是的,在这两个声明中,T 应该被推断为 void (&)() - aschepler
显示剩余4条评论
2个回答

4

为什么要使用void operator<<(T&& x)void operator<<(T& x)可以满足需求。

在重载函数中,可以使用x()调用该函数,如下所示:

struct A
{
    template<typename T>
    void operator<<(T& x)
    {
        x();
    }

};
void f()
{
}

int main()
{
    A().operator<<( f );
    A() << f;             
    return 0;
}

1
不,我使用右值引用,这样临时的函数对象就会被移动而不是复制。对于函数来说,两种方式都可以达到相同的效果。 - dsi

3

因此,回答我的问题:

提供的代码是有效的,虽然函数的右值引用是允许的(它们与左值引用的行为相同),但在模板推导期间,T应该变成void(&)()。

MSVC中的一个错误阻止了我的代码编译。

更新: Visual Studio 2013编译器已经修复了这个错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接