我想构建一个可以存储和调用多个tr1 :: functions的通用对象。
到目前为止,我使用了typedef和vector将它们存储在对象的成员字段中,例如
typedef tr1::function<void (SomeObject)> SomeFunction;
和
vector<SomeFunction> functionStorage
这有效,但我必须复制用于在每个对象中添加和调用函数的代码。所以我试着提出一个更通用的解决方案。理想情况下,我想要一些模板对象,我可以直接传递函数typedef,包括返回类型和参数类型,如
template<typename T>
class FunctionStore
{
public:
FunctionStore<T>();
virtual ~FunctionStore<T>();
void addFunction( const T &newFunction);
void callAllFunctions( const Parameter & parameter ) const;
private:
vector<T> functionStorage;
};
但这并没有成功,因为我无法从模板中获取参数列表以正确定义callAllFunctions
函数。
然后我试图忽略正确地为整个tr1 :: function定义类型的选项,并将其拆分为类本身内的returnType和parameterType,这种方法有效,但只有固定数量的参数:
template<typename R = void, typename P1 = void>
class FunctionStore
{
typedef tr1::function<R( P1 & )> Function;
public:
FunctionStore<R, P1>();
virtual ~FunctionStore();
void addFunction( const Function &newFunction )
{
functionStorage.push_back(newFunction);
}
void callAllFunctions( const P1 ¶meter ) const
{
for( Function fn : functionStorage)
{
fn(parameter);
}
}
private:
vector<Function> functionStorage;
};
但有了这个,我无法真正使P1 Type成为可选项。我尝试将其默认为无效,但因为我将其用作P1 & parameter
,它会评估为期望fn(void &)
,这与fn()
不同。此外,不使用&
不起作用,因为它会创建一个非法的void引用。我还考虑了可变参数,因为它可以解决可选的需求,但由于参数数量和类型显然实际上是在类型中定义的(并且需要tr1 :: bind占位符的东西),这似乎是错误的方式去吧。
那么我该如何实现呢?我认为没有真正的方法可以使第一个选项(我显然更喜欢)发生,所以第二个选项的解决方案仍然非常受欢迎。
答案 0 :(得分:0)
使用C ++ 11和可变参数模板,您可以执行以下操作:
template<typename R = void, typename... Args>
class FunctionStore
{
typedef tr1::function<R(const Args&)> Function;
public:
FunctionStore<R, P1>();
virtual ~FunctionStore();
void addFunction( const Function &newFunction )
{
functionStorage.push_back(newFunction);
}
void callAllFunctions(const Args... ¶meters) const
{
for( Function fn : functionStorage)
{
fn(parameters...);
}
}
private:
vector<Function> functionStorage;
};
答案 1 :(得分:0)
专营:
template<class Sig>
class FunctionStore;
template<class R, class...Args>
class FunctionStore<R(Args...)> {
typedef std::tr1::function<R( Args... )> Function;
public:
FunctionStore() {}
virtual ~FunctionStore() {}
void addFunction( Function f ) {
functionStorage.emplace_back(std::move(f)); // or push_back on C++03
}
template<class...Ts>
void callAllFunctions( Ts&&... ts) const
{
for( auto&& fn : functionStorage) {
bool last_iteration = &fn == functionStorage.data()+functionStorage.size()-1;
if (last_iteration)
fn(std::forward<Ts>(ts)...);
else
fn(ts...); // or remove all the rest of the loop body, and just fn(ts...)
}
}
private:
std::vector<Function> functionStorage;
};
现在,last_iteration
可能是太多的微优化。只需fn(args...)
。
现在,上面使用完美转发而不是callAllFunctions
的显式参数,完美转发非常不完美。您可以改为使用callAllFunctions( Args... args )
参数进行签名template
,这样就可以基于{}
构建等等。