制作复合std :: function

时间:2014-04-10 19:36:52

标签: c++ tr1

我创建了这个仿函数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

2 个答案:

答案 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);
}