C ++非类型参数包扩展 [英] c++ non-type parameter pack expansion

查看:186
本文介绍了C ++非类型参数包扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写通过单一类型参数化的模板函数,并且具有可变数量的相同类型(而不是不同类型)的参数。它应该检查第一个值是否在其余值中。我想这样写:

I am writing template function that is parametrized by single type, and has variable number of parameters of the same type (not of different types). It should check if first value is among the rest. I wanted to write it like this:

#include <unordered_set>

template <typename T>
static bool value_in(T val, T vals...) {
    // compiles, but uses only vals[0]:
    const std::unordered_set<T> allowed {vals};
    // error: pack expansion does not contain any unexpanded parameter packs:
    // const std::unordered_set<T> allowed {vals...};
    return allowed.find(val) != allowed.end();
}
// usage
enum class Enumeration {one, two, three};
int main () {
    // should return true -> 0
    return value_in(Enumeration::two,
                    Enumeration::one,
                    Enumeration::two) ? 0 : 1;
}

我期望第二个可以工作,但是它不能编译,因为

I expected that second to work, but it doesn't compile because

test.cpp: In function ‘bool value_in(T, T, ...)’:
test.cpp:7:46: error: expansion pattern ‘vals’ contains no argument packs

我看到 (T,T,...)而不是 (T,T ...),所以我大概弄乱了函数声明,并以C风格的可变参数函数结束。

I see the "(T, T, ...)" instead of "(T, T...)", so probably I messed up function declaration and ended with C-style variadic function.

如何编写将接受任意数量 same 类型参数的声明?

How to write declaration that will accept arbitrary number of parameters of the same type?

推荐答案

我在这里看到两个选项。您可以传递 std :: initializer_list ,这会使函数签名更改为

I see two options here. You can pass a std::initializer_list, which causes the function signature to change to

#include <initializer_list>

template <typename T>
static bool value_in(T&& val, std::initializer_list<T> vals)
{
    /* Implementation as before */
}

和调用代码段

return value_in(Enumeration::two,
      { Enumeration::one, Enumeration::two }) ? 0 : 1;

请注意此处的其他花括号,它们是构造要传递的初始化程序列表所必需的。这种方法的一个小细节是函数签名,它立即表明只有一种类型可以推断。

Note the additional braces here, they are required to construct the initializer list to be passed. A little detail of this approach is the function signature, which immediately reveals that there is only one type to deduce.

如果键入括号感觉有误,请坚持使用原始尝试并调整功能,以使

If it feels wrong to type the braces, stick with your original attempt and tweak your function such that

template <typename S, typename... T>
static bool value_in(S&& val, T&&... vals) {
   const std::unordered_set<S> allowed {std::forward<T>(vals)...};

   /* As before... */
}

这允许您像原始代码片段中那样调用该函数。与上述解决方案相比,此签名显然具有两个模板参数,如果 S 不同,则可能需要再次查看才能失败。 T

This allows for calling the function as in your original snippet. In contrast to the above solution, this signature obviously has two template parameters, which might require a second look to see that it will fail if S differs from T.

这篇关于C ++非类型参数包扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆