C++ How to store a parameter pack as a variable

后端 未结 2 421
梦谈多话
梦谈多话 2020-12-13 07:12

At the moment I am having trouble trying to store a parameter pack, this is example code of the design:

template
void          


        
相关标签:
2条回答
  • 2020-12-13 07:35

    Edit from 2018: In C++17 the answer to this question is different. You still have to store your arguments in a ::std::tuple, but when the time comes to call the function ::std::apply handles unpacking this tuple and calling the function for you. And if you need to use the indices trick for something other than what ::std::apply does, there's ::std::integer_sequence and the associated helper function, ::std::make_index_sequence that you should investigate.

    Now back to your C++11/14 answer from way back in 2013.

    You have to use ::std::tuple<Args...> to store it. But then the question is how to unpack it when you need it. For that you need to use a technique called 'indices'.

    So, here is a link to a place where I've done approximately what you're looking to do. The most relevant class here that's sort of the centerpiece is suspended_call.

    https://bitbucket.org/omnifarious/sparkles/src/tip/sparkles/deferred.hpp?at=default

    In just a bit, I'll extract the most relevant bits and put them in terms of your code.

    This line:

    auto saved_args = ::std::make_tuple(::std::move(args)...);
    

    saves the arguments into a tuple. I used ::std::move there, and I think that's the right thing to do. But it's possible I'm wrong and I should use ::std::forward. I've never been clear on the exact difference aside from signaling intent.

    The code that actually does the call with the saved arguments can be found here. Now that code is fairly specific to exactly what I'm doing. The bit that implements the indices trick involves creating a pack of integers that maps to the indices to use as arguments the ::std::get<I> template. Once you have this pack of integers, you can then use it to expand the call to ::std::get to get all the tuple elements as individual arguments.

    I'll try to come up with code that does that in a relatively straightforward way:

    #include <tuple>
    #include <cstddef>
    #include <string>
    #include <utility>
    
    template < ::std::size_t... Indices>
    struct indices {};
    
    template < ::std::size_t N, ::std::size_t... Is>
    struct build_indices : build_indices<N-1, N-1, Is...>
    {};
    
    template < ::std::size_t... Is>
    struct build_indices<0, Is...> : indices<Is...>
    {};
    
    template <typename FuncT, typename ArgTuple, ::std::size_t... Indices>
    auto call(const FuncT &f, ArgTuple &&args, const indices<Indices...> &)
       -> decltype(f(::std::get<Indices>(::std::forward<ArgTuple>(args))...))
    {
       return ::std::move(f(::std::get<Indices>(::std::forward<ArgTuple>(args))...));
    }
    
    template <typename FuncT, typename ArgTuple>
    auto call(const FuncT &f, ArgTuple &&args)
         -> decltype(call(f, args,
                          build_indices< ::std::tuple_size<ArgTuple>::value>{}))
    {
        const build_indices< ::std::tuple_size<ArgTuple>::value> indices;
    
        return ::std::move(call(f, ::std::move(args), indices));
    }
    
    int myfunc(::std::string name, const unsigned int foo)
    {
       return 0;
    }
    
    int foo(::std::tuple< ::std::string, const unsigned int> saved_args)
    {
       return call(myfunc, ::std::move(saved_args));
    }
    

    A lot of this code was borrowed from this page on the indices trick.

    Also, that's sort of a sample that you will have to adapt slightly to your specific situation. Basically, just call call(nestFunc, saved_args) somewhere.

    0 讨论(0)
  • 2020-12-13 07:46

    I know it's been a while but I had similar needs and came up with this solution, hope it helps someone:

    #include <functional>
    
    template<typename Func, typename... Args>
    struct nest {
        std::function<void()> callBack;
    
        void setup(Func func1, Args... args) {
            callBack = [func1, args...]()
            {
                (func1)(args...);
            };
        }
    
        unsigned process() {
            callBack();
            return 0;
        }
    };
    
    template<typename Func, typename... Args>
    void handleFunc(Func func, Args&&... args) {
        nest<Func, Args...> myNest;
        myNest.setup(func, args...);
    }
    
    0 讨论(0)
提交回复
热议问题