【问题标题】:Obtain Argument Index while Unpacking Argument List with Variadic Templates使用可变参数模板解包参数列表时获取参数索引
【发布时间】:2013-02-08 18:32:09
【问题描述】:

我需要在解包和转换参数列表时获取参数的索引。 以下问题有没有解决办法:

#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);
}

【问题讨论】:

  • 请解释您试图找到解决方案的原因。
  • 这看起来像是在尝试创建一个元组——为什么..?

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


【解决方案1】:

我会这样做。首先,您需要一些机制来创建整数的编译时序列:

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;

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

然后,您可以使用该机制来实现函数调用,利用参数包扩展的力量:

#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);
}

【讨论】:

  • 有一个应用程序--- a page。 ;)
  • @Xeo:你什么意思? :) 那是我应该链接的官方内容吗?我知道 Jonathan Wakely 有一个标准提议来介绍 int_seq
  • 谢谢安迪,这是我一直在寻找的东西。效果很好!
  • @user2101363:不客气。如果它解决了您的问题,请考虑接受答案:-)
【解决方案2】:

最简单的解决方案肯定是不使用void*vector;直接使用值:

template<typename...Arg>
void call_test(Arg const&...arg) {
  test(arg...);
}

(或该主题的一些变体。)但我想您想做的不仅仅是调用测试。

如果您真的想要索引,请使用这里所谓的“索引技巧”。你应该可以搜索到。

【讨论】:

  • 没有向量是一个不同的问题(或者不是问题:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多