我正在尝试创建一个函数,将任意仿函数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 :(得分:6)
这是您收到“已删除的构造函数”错误的问题:
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
工作,看起来不是这样,你也会有一个模糊的调用。我认为您还需要禁用主要案例。
答案 1 :(得分:0)
实例化std::function<void(A)>
时,实例化具有A
值的签名的函数。要合成此函数定义,需要复制或移动A
。由于A
不可复制但不可移动,因此这样的构造函数不存在。
当然,也有这个有趣的事情:
T t();
声明函数按需要复制的值返回T
。调用ForEachTuple(t, f)
时,会引用并实例化此函数。您可能希望用
T t;
T t{};
(在上面的回答中我只看了我发现的第一个问题)。