使用可变参数模板将存储在std :: vector中的void *转换为函数参数

时间:2014-03-30 13:27:53

标签: templates c++11 variadic-templates void-pointers

我创建了一个MemberFunctionWrapper模板类,用于存储函数及其参数类型。它有一个调用方法,它接受void *的向量,并在调用函数之前将它们转换为函数调用所需的参数类型。

我的问题是包装器只能接受固定数量的函数参数 (_arg0,_arg1)。
我希望该类可以使用任意数量的函数参数(arg0,arg1,arg2 ... argX)如何实现这一目标?

提前致谢

class Foo
{
public:
    void foo( int a, const string& b );
};

template< class _obj, class _function, class _arg0, class _arg1 >
class MemberFunctionWrapper
{
    const _function m_memberfunction;

public:
    MemberFunctionWrapper( _function memFn )
        : m_memberfunction( memFn )
    { }

    void call( std::shared_ptr<void>& obj,
               const std::vector<std::shared_ptr<void>>& args )
    {
        m_memberfunction( *static_cast< _obj* >(obj.get()),
                          *static_cast< _arg0* >(args.at( 0 ).get()),
                          *static_cast< _arg1* >(args.at( 1 ).get()) );
    }

};

int main()
{
    std::shared_ptr<int> i( new int( 88 ) );
    std::shared_ptr<string> s( new string( "hello" ) );
    std::shared_ptr<Foo> foo( new Foo );

    std::shared_ptr<void> iVoid = std::static_pointer_cast< void >(i);
    std::shared_ptr<void> sVoid = std::static_pointer_cast< void >(s);
    std::shared_ptr<void> fooVoid = std::static_pointer_cast< void >(foo);

    MemberFunctionWrapper
    <
        Foo,
        decltype(std::mem_fn( &Foo::foo )),
        int,
        string
    > wrapper( &Foo::foo );

    wrapper.call( fooVoid, std::vector<std::shared_ptr<void>>{iVoid, sVoid} );

    system( "pause" );
}

1 个答案:

答案 0 :(得分:0)

以下可能有所帮助:https://ideone.com/l7yAJN

template<typename F> class MemberFunctionWrapper;

template<class Obj, class Ret, typename ... Args>
class MemberFunctionWrapper<Ret (Obj::*)(Args...)>
{
    typedef Ret (Obj::*MemberFunction)(Args...);
    const MemberFunction m_memberfunction;

    template <std::size_t ... Is>
    void call(std::shared_ptr<void>& obj,
              const std::vector<std::shared_ptr<void>>& args,
              index_sequence<Is...>)
      {
          (static_cast<Obj*>(obj.get())->*m_memberfunction)
              (*static_cast<typename std::remove_reference<Args>::type*>(args.at(Is).get())...);
      }
public:
    MemberFunctionWrapper(MemberFunction memFn) : m_memberfunction(memFn)
    {}

    void call(std::shared_ptr<void>& obj,
              const std::vector<std::shared_ptr<void>>& args )
    {
        assert(args.size() == sizeof...(Args));
        call(obj, args, make_index_sequence<sizeof...(Args)>());
    }

};