通用可选功能参数

时间:2014-12-11 16:51:19

标签: c++ templates generics function-pointers

我想构建一个可以存储和调用多个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 &parameter ) const
        {
            for( Function fn : functionStorage)
            {
                fn(parameter);
            }
        }

    private:
        vector<Function> functionStorage;
};

但有了这个,我无法真正使P1 Type成为可选项。我尝试将其默认为无效,但因为我将其用作P1 & parameter,它会评估为期望fn(void &),这与fn()不同。此外,不使用&不起作用,因为它会创建一个非法的void引用。我还考虑了可变参数,因为它可以解决可选的需求,但由于参数数量和类型显然实际上是在类型中定义的(并且需要tr1 :: bind占位符的东西),这似乎是错误的方式去吧。

那么我该如何实现呢?我认为没有真正的方法可以使第一个选项(我显然更喜欢)发生,所以第二个选项的解决方案仍然非常受欢迎。

2 个答案:

答案 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... &parameters) 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,这样就可以基于{}构建等等。

相关问题