C++ 17 可以处理嵌套的可变参数模板吗?
Can C++ 17 handle nested variadic templates?
考虑下面的C++ 17代码,该代码测试一组枚举值以查看该集合中是否包含另一个枚举值:
enum Flag { val1, val2, val3, val4, val5 };
template<Flag arg> struct Value {
template<Flag... set> struct IsIn {
static constexpr bool value =
static_cast<bool>(((set == arg) || ...));
};
};
这按预期工作:
bool x = Value<val4>::IsIn<val1, val2, val5>::value;
// x == false
bool y = Value<val2>::IsIn<val3, val2>::value;
// y == true
但是,我想测试一组值是否都包含在另一组值中,如下所示:
template<Flag... args> struct Values {
template<Flag... set> struct AreIn {
static constexpr bool value =
static_cast<bool>((Value<args>::IsIn<set...>::value && ...));
};
};
以上不是在GCC 7.3或Clang 5.0上编译的;它们都给出了相当神秘的答案,对问题几乎没有洞察力。鉴于允许在模板参数列表中扩展参数包(只要模板支持扩展),我很难弄清楚为什么这不是合法C++。
您遇到了C++语法中最令人恼火的问题之一:不可推断的依赖名称。
当你做Foo<Bar>::Baz<Quux>
时,由于Foo<Bar>
是一个依赖名称,你必须把template
关键字放在Baz
之前,以防止解析器跑掉悬崖。Clang通常非常擅长用一个有用的错误明确地告诉你这一点,但在某些情况下(比如你的),它只是爆炸并说Expected )
或同样无益的东西。
有关详细信息,请参阅此其他问题
因此,要修复模板,您所要做的就是在依赖模板调用中添加template
关键字:
template<Flag... args>
struct Values {
template<Flag... set>
struct AreIn {
static constexpr bool value =
static_cast<bool>((Value<args>::template IsIn<set...>::value && ...));
};
};
另请注意,static_cast<bool>()
是多余的。
这解决了您的问题:替换
static_cast<bool>((Value<args>::IsIn<set...>::value && ... ))
由
static_cast<bool>((Value<args>::template IsIn<set...>::value && ... ))
这是为什么呢?在解析AreIn
声明时,编译器无法知道Value<args>
可能解析为哪些可能的类型。也许,在文件的稍后时刻,您将声明不包含模板子类IsIn
而是该名称字段的Values
专用化。使用template
关键字向编译器承诺IsIn
应该是某种模板,因此以下<
...>
被解析为模板参数,而不是使用set...
和::value
(全局命名空间中的变量)进行比较运算符,这也是有意义的。
当然,有人可能会问为什么编译器不等到它知道你正在使用Values<val1, val2>
,为此确实有一个模板化子类AreIn<val1, val2, val5>
它有一个静态成员::value
。但是,提前解析并记住部分处理的语法树正是当今编译器的工作方式,并且由于上述原因,该标准使template
提示成为强制性的。
- 在不传递参数数量且只有3个点的情况下,如何使用变差函数
- 如何使用可变参数模板强制转换每个变体类型
- 关于如何在具有单个参数的变体构造中选择替代方案?
- 调用参数排列不变函数 f(i++, i++)
- 参数归纳与标准::变体
- 模板化回调参数的逆变,如 C# 中的逆变
- 如何在没有参数包的情况下编写变差函数
- 通过具有嵌套类的工厂类获取多个变异类模板参数包
- 获取模板参数的成员变量值列表
- 保留短 lambda 用作函数的中间参数,使用 clang 格式保持不变
- 如何定义变体<x,y,z>提取模板参数的子类型
- 正确对齐内存模板,参数顺序不变
- 递归中不同参数类型的变元模板函数
- 通过函数指针传递给变差函数的参数会更改其值
- 提升预定义为带有参数的全局 lambda 的变体访问者
- 使用可变参数模板参数提升变体访问者
- boost ::变体 - 为什么模板参数比const字符串参数具有更高的优先级
- 将变参数包中的值加载到临时数组中
- 使用额外参数提升变体访客
- 正在将动态数组元素解析为参数?(变音符)