可以将std :: function从rvalue引用移动构造到临时的functor对象吗?

Cra*_*rks 18 c++ std rvalue-reference c++11

我有一个untemplated仿函数对象,我试图存储为std::function另一个对象内部.这个对象非常重量级,因此它被标记为不可复制,但它确实有一个移动构造函数.但是,尝试从临时构造函数构造std :: function或分配它失败.

这是引发错误的最小示例.

// pretend this is a really heavyweight functor that can't be copied.
struct ExampleTest
{
    int x;
    int operator()(void) const {return x*2;}
    ExampleTest(  ) :x(0){}
    ExampleTest( int a ) :x(a){}

    // allow move
    ExampleTest( ExampleTest &&other ) :x(other.x) {};

private: // disallow copy, assignment
    ExampleTest( const ExampleTest &other );
    void operator=( const ExampleTest &other );
};

// this sometimes stores really big functors and other times stores tiny lambdas.
struct ExampleContainer
{
    ExampleContainer( int );
    std::function<int(void)> funct;
};

/******** ERROR:
 Compiler error: 'ExampleTest::ExampleTest' : cannot access private member 
 declared in class 'ExampleTest'
******************/
ExampleContainer::ExampleContainer( int x )
    : funct( ExampleTest( x ) ) 
{}

/******** ERROR:
 Compiler error: 'ExampleTest::ExampleTest' : cannot access private member 
 declared in class 'ExampleTest'
******************/
int SetExample( ExampleContainer *container )
{
    container->funct = ExampleTest();
    return container->funct();
}
Run Code Online (Sandbox Code Playgroud)

在一个更简单的构造中,我只是在创建一个本地函数,我也得到错误:

int ContrivedExample(  )
{
    // extra parens to sidestep most vexing parse 
    std::function<int()> zug( (ExampleTest()) );
    /*** ERROR: 'ExampleTest::ExampleTest' : cannot access private member
         declared in class 'ExampleTest' */
    int troz = zug(  ) ;
    return troz;
}
Run Code Online (Sandbox Code Playgroud)

据我所知,在所有这些情况下,临时的ExampleTest应该作为右值传递给函数构造函数.然而编译器想要复制它们.

是什么赋予了?是否可以将不可复制(但可移动复制)的仿函数对象传递给std :: function构造函数?有指针等的解决方法,但我想了解这里发生了什么.

上面的具体错误来自Visual Studio 2012和CTP C++ 11补丁.GCC 4.8和Clang 3也会出现故障,并带有自己的错误消息.

And*_*owl 18

这个对象非常重量级,因此它被标记为不可复制,但它确实有一个移动构造函数.

如果仿函数是不可复制的,则它不符合使用的必要条件std::function.C++ 11标准的第20.8.11.2.1/7段规定:

template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);
Run Code Online (Sandbox Code Playgroud)

7 要求:F应该是CopyConstructible.对于参数类型 和返回类型,f应为Callable(20.8.11.2).复制构造函数和析构函数不应抛出异常.ArgTypesRA

  • 虽然标准很清楚,它想要使用复制结构,但我并不认为有任何需要这样做!也许它值得一个缺陷报告.我快速浏览了现有报告,但我没有看到提到这个问题.我猜这是TR1类导入C++ 2011时的疏忽. (9认同)
  • 我之前注意到了这一点,但标准还指出"每个调用包装器(20.8.1)应该是MoveConstructible",而`function`有一个rvalue-taking移动构造函数.这似乎是矛盾的. (2认同)