Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
611 views
in Technique[技术] by (71.8m points)

c++ - Obtain Argument Index while Unpacking Argument List with Variadic Templates

I need to obtain the index of an argument while unpacking and converting argument list. Is there any solution for the following problem:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

void test(int a, std::string b, bool c)
{
    cout << a << "," << b << "," << c << endl ;
}

template <typename... ARG>
static void call_test(const vector<void*> &params)
{
    test(*static_cast<ARG*>(params[ indexOf(ARG) ])...);
}

int main(int argc, char **argv)
{
    int    a = 1;
    string b = "string";
    bool c   = false;
    vector<void*> v(3);
    v[0] = &a;
    v[1] = &b;
    v[2] = &c;

    call_test<int,string,bool>(v);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is how I would do it. First of all, you will need some machinery to create compile-time sequences of integers:

using namespace std;

//===========================================================================
// META-FUNCTIONS FOR CREATING INDEX LISTS

// The structure that encapsulates index lists
template <size_t... Is>
struct index_list
{
};

// Collects internal details for generating index ranges [MIN, MAX)
namespace detail
{
    // Declare primary template for index range builder
    template <size_t MIN, size_t N, size_t... Is>
    struct range_builder;

    // Base step
    template <size_t MIN, size_t... Is>
    struct range_builder<MIN, MIN, Is...>
    {
        typedef index_list<Is...> type;
    };

    // Induction step
    template <size_t MIN, size_t N, size_t... Is>
    struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...>
    {
    };
}

// Meta-function that returns a [MIN, MAX) index range
template<size_t MIN, size_t MAX>
using index_range = typename detail::range_builder<MIN, MAX>::type;

//===========================================================================

Then, you could use that machinery for realizing the function call, exploiting the power of argument pack expansion:

#include <iostream>
#include <vector>
#include <string>

void test(int a, std::string b, bool c)
{
    cout << a << "," << b << "," << c << endl ;
}

namespace detail
{
    // This is the function that does the real work.
    template<typename... Ts, size_t... Is>
    void call_test(const vector<void*>& params, index_list<Is...>)
    {
        test((*static_cast<Ts*>(params[Is]))...);
    }
}

// This function just creates the compile-time integer sequence and 
// forwards to another function that performs the real work.
// In other words, this is a proxy that hides the complexity of the
// machinery from the client.
template <typename... ARG>
void call_test(const vector<void*>& params)
{
    detail::call_test<ARG...>(params, index_range<0, sizeof...(ARG)>());
}

int main(int argc, char **argv)
{
    int    a = 1;
    string b = "string";
    bool c   = false;
    vector<void*> v(3);
    v[0] = &a;
    v[1] = &b;
    v[2] = &c;

    call_test<int,string,bool>(v);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...