简体   繁体   English

c++ 从模板中解包参数包 arguments

[英]c++ Unpacking parameter pack from template arguments

How to achieve want I want below?如何实现下面我想要的? The paramater pack I want to unpack is not in a function argument list but template argument list.我要解压的参数包不在 function 参数列表中,而是模板参数列表中。

#include <iostream>
#include <array>

const std::size_t SIZE = 10;

template <int...ARGS>
std::array<bool, SIZE> func() {
    std::array<bool, SIZE> b;
    // I want to set b[n] = true, where n takes on all values from ARGS...
    // what to put in here???
    return b;
}

// Example of what I want to achieve:
int main() {
    const std::array<bool, SIZE> b = func<1,3,7>();
    // I want b[1]==true, b[3]==true, b[7]==true, all others false
    for (int x: b) std::cout << x << std::endl;
}

I have to use this form for func (instead of func(1,3,7)) to get my bigger program working (I'm dealing with multiple inheritance issues).我必须将这种形式用于 func(而不是 func(1,3,7))以使我的更大的程序运行(我正在处理多个 inheritance 问题)。

Recursive template solution: 递归模板解决方案:

// recursive helper struct
template <int n, int First, int ...Rest>
struct helper {
  static void funcImpl(std::array<bool, SIZE>& temp) {
    temp[First] = true;
    helper<n - 1, Rest...>::funcImpl(temp);
  }
};

// partial specialization to catch base case
template <int First>
struct helper<0, First> {
  static void funcImpl(std::array<bool, SIZE>& temp) {
    temp[First] = true;
  }
};

template <int ...Args>
std::array<bool, SIZE> func() {
    std::array<bool, SIZE> b = {}; // 0 inititalize array
    helper<sizeof...(Args) - 1, Args...>::funcImpl(b);
    return b;
}

EDIT: A super simplified version inspired by iavr's solution: 编辑:受iavr解决方案启发的超简化版本:

template <int... A>
std::array<bool, SIZE> func() {
    std::array<bool, SIZE> b = {};
    auto values = {A...};
    std::for_each(values.begin(), values.end(), [&](int n){b[n] = true;});
    return b;
}

Here is a much simpler solution that requires nothing extra, just this: 这是一个更简单的解决方案,不需要额外的东西,只需这样:

struct _do { template <typename... T> _do(T&&...) { } };

template <int... A>
std::array<bool, SIZE> func() {
    std::array<bool, SIZE> b = {};
    _do{b[A] = true...};
    return b;
}

This assumes the array is first initialized and then populated. 这假设首先初始化数组然后填充。 My previous solution computed all values at compile time and directly initialized the array with them. 我之前的解决方案在编译时计算了所有值,并直接用它们初始化了数组。 So this is probably faster to compile and slower to run. 因此编译速度可能更快,运行速度也更慢。

Since C++17, you can use fold expressions :自 C++17 起,您可以使用折叠表达式

template <std::size_t... ARGS>
constexpr std::array<bool, SIZE> func() {
    std::array<bool, SIZE> b{};
    ((b[ARGS] = true), ...);    // fold expression
    return b;
}

Demo演示


For C++11 and 14, I'd prefer using an unnamed lambda, like this:对于 C++11 和 14,我更喜欢使用未命名的 lambda,如下所示:

template <std::size_t... ARGS>
std::array<bool, SIZE> func() {
    std::array<bool, SIZE> b{};
    [](...){}(b[ARGS] = true...);
    return b;
}

See live example . 查看实例

Here's the implementation of func : 这是func的实现:

template <int... A, int... N>
std::array<bool, sizeof...(N)>
func(sizes <N...>)
{
    return std::array<bool, sizeof...(N)>{{in <N, A...>()...}};
}

template <int... A>
std::array<bool, SIZE>
func() { return func <A...>(range <SIZE>()); }

where sizes represents an int sequence, range <S> constructs sequence 0,...,S-1 and in<N, A...>() checks whether number N is in sequence A... (definitions in the live example). 其中sizes表示一个int序列, range <S>构造序列0,...,S-1并且in<N, A...>()检查数字N是否在序列A... (在现场定义)例)。

This not the most efficient (compile-wise) way to implement, because for every element of N... we need to scan pack A... . 这不是最有效(编译方式)的实现方式,因为对于N...每个元素N...我们需要扫描包A... It's better to scan packs A... , L... in parallel, with a modification of function in() . 最好是并行扫描包A...L... ,并修改in()的函数。 But anyway this was more straightforward to think of and write down. 但无论如何,这更容易思考和写下来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM