我创建了这个仿函数Functions
,用于存储多个std::functions
,并按顺序调用它们,就像它本身是std::function
一样:
typedef std::function <void (int)> FuncType;
struct Functions
{
vector<FuncType> m;
void operator+= (FuncType f) {
m.push_back(f);
}
void operator() (int param ){ // same prototype as FuncType
vector<FuncType>::iterator it;
for(it=m.begin(); it!=m.end(); ++it) {
(*it)(param);
}
}
};
它非常有用,因为它可以存储在FuncType
:
int main()
{
Functions f;
f += foo;
f += bar;
FuncType ptr(f);
ptr(10); // calls foo(10), then bar(10)
}
它工作正常,但我希望能够使这个成为模板化的算子。但我想不出让operator()
遵循函数原型的方法:
template <typename FuncType> // for any Function type
struct Functions
{
vector<FuncType> m;
void operator+= (FuncType f) {
m.push_back(f);
}
void operator() (...) { // how do I get the same prototype as FuncType?
vector<FuncType>::iterator it;
for(it=m.begin(); it!=m.end(); ++it) {
(*it)(...);
}
}
};
理想情况下,我还希望有一个辅助函数,它实例化仿函数(当然,所有函数都具有相同的原型),如下所示:
template <typename T>
Functions<T> make_functions( T funcA, T funcB ) {
Functions<T> f;
f += funcA;
f += funcB;
return f;
}
但我不确定编译器是否可以推断T
是std :: function&lt;&gt;某种。
我正在使用std::tr1
答案 0 :(得分:5)
template<typename Sig> struct Functions;
template<typename R, typename... Args>
struct Functions<R(Args...)>{
typedef std::function<R(Args...)> FuncType;
std::vector<FuncType> fs;
void operator+=(FuncType f){fs.emplace_back(std::move(f));}
template<typename...Us>
void operator()(Us&&...us){
for(auto&&f:fs)
f(us...);
}
};
int main(){
Functions<void(int)> funcs;
funcs += [](int x){ std::cout<<x<<"\n";};
funcs(7);
}
真正完美的转发和收集返回值作为练习。
答案 1 :(得分:3)
这样的事情怎么样?编辑:正如所指出的那样,我错过了make_function
,并有机会用std::forward
完美地转发论点。 http://coliru.stacked-crooked.com/a/f597aacd3b7ce404
#include <functional>
#include <iostream>
#include <vector>
template<typename T, typename... Args>
class Functions
{
private:
std::vector<std::function<T(Args...)>> vec;
public:
void operator += (std::function<T(Args...)> f)
{
vec.push_back(f);
}
void operator()(Args... args)
{
for (auto &f : vec)
{
f(std::forward<Args>(args)...);
}
}
};
int main()
{
Functions<void> funcs;
funcs += []{std::cout<<"Foo\n";};
funcs += []{std::cout<<"Bar\n";};
funcs();
std::cout<<"\n";
Functions<void, int> funcs2;
funcs2 += [](int a){std::cout<<"Foo"<<a<<"\n";};
funcs2 += [](int b){std::cout<<"Bar"<<b<<"\n";};
funcs2(2);
}