2014-11-05 67 views
0

我试图创建适用任意函子F到所提供的元组的每个元素的功能:错误:使用删除的功能。为什么?

#include <functional> 
#include <tuple> 

// apply a functor to every element of a tuple 
namespace Detail { 

template <std::size_t i, typename Tuple, typename F> 
typename std::enable_if<i != std::tuple_size<Tuple>::value>::type 
ForEachTupleImpl(Tuple& t, F& f) 
{ 
    f(std::get<i>(t)); 
    ForEachTupleImpl<i+1>(t, f); 
} 

template <std::size_t i, typename Tuple, typename F> 
typename std::enable_if<i == std::tuple_size<Tuple>::value>::type 
ForEachTupleImpl(Tuple& t, F& f) 
{ 
} 

} 

template <typename Tuple, typename F> 
void ForEachTuple(Tuple& t, F& f) 
{ 
    Detail::ForEachTupleImpl<0>(t, f); 
} 

struct A 
{ 
    A() : a(0) {} 
    A(A& a) = delete; 
    A(const A& a) = delete; 

    int a; 
}; 

int main() 
{ 
    // create a tuple of types and initialise them with zeros 
    using T = std::tuple<A, A, A>; 
    T t; 

    // creator a simple function object that increments the objects member 
    struct F 
    { 
     void operator()(A& a) const { a.a++; } 
    } f; 

    // if this works I should end up with a tuple of A's with members equal to 1 
    ForEachTuple(t, f); 
    return 0; 
} 

直播的代码示例:http://ideone.com/b8nLCy

我不希望创建的A因为副本它可能是昂贵的(显然在这个例子中它不是),所以我删除了拷贝构造函数。当我运行上面的程序我得到:

/usr/include/c++/4.8/tuple:134:25: error: use of deleted function ‘A::A(const A&)’ 
     : _M_head_impl(__h) { } 

我知道构造函数被删除(这是故意的),但我不明白的是为什么它试图让我的结构的副本。为什么会发生这种情况,如何在不复制A的情况下实现这一目标?

+0

是不是有一种调用堆栈显示试图使用元组副本构造函数? – 2014-11-05 04:07:19

+0

由于这是一个与助推相关的问题,我建议添加boost标签。 – 2014-11-05 04:07:23

+0

@ D'Nabre:真的不是。这是一个关于为什么'std :: tuple'试图首先复制它的成员的问题。 – 2014-11-05 04:08:00

回答

4

这是你得到了“已删除构造函数”错误的问题:

std::function<void(A)> f = [](A& a) { a.a++; }; 

你试图建立一个std::function是按值传递的A。但A,没有复制构造函数,不能通过值传递。

尝试更仔细地匹配实际的参数类型:

std::function<void(A&)> f = [](A& a) { a.a++; }; 

但是因为你没有捕捉变量,你可以简单地尝试

void(*f)(A&) = [](A& a) { a.a++; }; 

你还要一个重大问题与你的模板递归的基本情况:即使你的enable_if工作,它似乎不是,你会有一个模糊的电话。我想你还需要禁用的主要情况。

+0

我改变了它,同样的错误:http://ideone.com/b8nLCy – arman 2014-11-05 04:16:10

+0

@quant看起来错误来自'T t(0,0,0);'行。 *“prog.cpp:41:18:需要从这里开始”*然而,如果你确定你仍然会遇到Ben指出的问题,那么看起来他的答案是正确的,但并不完整。 – cdhowie 2014-11-05 04:17:57

+0

@cdhowie是啊我认为构造函数是问题... – arman 2014-11-05 04:18:47

0

当实例化std::function<void(A)>时,实例化具有按值的A的签名的函数。为了综合这个函数定义,需要复制或移动A。由于A是不可复制的,但不能移动,所以这样的构造函数不存在。

当然,也有这样有趣的事:

T t(); 

该声明的函数,要求复制值返回T。当调用ForEachTuple(t, f)时,该函数被引用并实例化。您可能希望通过的

T t; 
T t{}; 

一个替换此声明(在回答以上我只是看着我看到的第一个问题)。