两种可变参数的展开

问题描述 投票:2回答:1

[两种类型的可变参数如何展开?这是我想要达到的目标:

#include <vector>
#include <iostream>

class test
{
public:
    std::vector< std::pair< float, int > > vec;
    template<typename... T1, typename... T2>
    test( T1... one, T2... two )
    {
        (
            [&](float first, int second)
            {
                vec.emplace_back( std::pair< float, int >( first, second ) );
                std::cout << first << ", " << second << std::endl;
            }( one, two ),
            ...
        );
    }
};

int main()
{
    test t
    {
        1.f,
        1,
        2.f,
        2,
        3.f,
        3
    };

    return 0;
}

test必须像在main中一样完全初始化。我希望测试的构造函数中的用法保持相似。

这里是va_list的工作概念。不幸的是,我需要传递参数的计数,或者需要传递幻数终止符(我选择了幻数终止符)。

#include <cstdarg>
#include <iostream>
#include <vector>

constexpr int END_OBJECT = 890123; // magic number

class test {
 public:
  std::vector<std::pair<int, double>> vec;

  enum { is_name, is_data, is_max };

  test(char ch, ...) {
    std::pair<int, double> buf;

    va_list b;
    va_start(b, ch);
    for (int i = 0;; i++) {
      auto is = i % is_max;

      if (is == is_name) {
        if ( (buf.first = va_arg(b, int)) == END_OBJECT )
            break;
      } else if (is == is_data) {
        buf.second = va_arg(b, double);
        vec.emplace_back(buf);
      }
    }
    va_end(b);
    std::cout << ch << std::endl;
    for (auto &x : vec)
      std::cout << '\t' << x.first << ", " << x.second << std::endl;
  }
};

int main() {
  test t
  {
    'x',
    1,
    2.0,
    3,
    4.0,
    5,
    6.0,
    END_OBJECT
  };

  return 0;
}

我想要使用pack-expansion的更新版本。

pub
1个回答
3
投票

有趣的是,这基本上是带有模板参数的FizzBu​​zz,这实际上是一个很好的挑战。

我想出的C ++ 14中最简单的方法是使用std :: index_sequence。https://godbolt.org/z/dm3F9u

#include <vector>
#include <utility>
#include <tuple>

template <typename... TArgs, size_t... Is>
std::vector<std::pair<float, int>> pair_off(std::tuple<TArgs...> args, std::index_sequence<Is...>) {
    return std::vector<std::pair<float, int>> { std::make_pair(std::get<(Is << 1)>(args), std::get<((Is << 1) + 1)>(args))... };
}


template <typename... TArgs>
std::vector<std::pair<float, int>> pair_off(TArgs&&... args) {
    return pair_off(std::forward_as_tuple(std::forward<TArgs>(args)...), std::make_index_sequence<(sizeof...(TArgs) >> 1)>{});
}

std::vector<std::pair<float, int>> test() {
    return pair_off(1.1f, 1, 2.2f, 2, 3.3f, 3);
}

[基本上,首先将参数打包到一个元组中。然后,使索引序列的大小为参数列表的一半。然后,您扩展该索引序列,将其传递到std :: get。

相当于模板的等同于:

for (int i=0; i<list.size()/2; i++) { 
    output.push_back( std::make_pair(list[i*2], list[i*2+1]) ); 
}
© www.soinside.com 2019 - 2024. All rights reserved.