我正在测试此代码(https://godbolt.org/z/fe6hhbeqW)...
// Returns the nth type in a parameter pack of types (ommited for clarity)
// template <std::size_t N, typename...Ts>
// nth_type{}
template <typename... Ts>
struct Typelist{
template <typename T>
consteval static std::size_t pos() noexcept {
for(std::size_t i{}; i < sizeof...(Ts); ++i) {
using TN = nth_type_t<i, Ts...>;
if (std::is_same_v<T, TN>)
return i;
}
return sizeof...(Ts);
}
};
我对它的不工作感到困惑。GCC和clang同意i
不是常量表达式,所以他们拒绝让我将其作为模板参数传递。然而,i
在编译时是清楚已知的,因此,就我有限的理解而言,编译器使用它来示例化模板应该没有任何问题。
有没有什么原因导致这不起作用?它将来会起作用吗?我已经用两个编译器的 Backbone.js 版本进行了测试,结果相同。
2条答案
按热度按时间8dtrkrch1#
当
i
的值在抽象意义上是已知的时,i
保证只在编译时求值并不重要。函数是
consteval
还是constexpr
或者都不是也没有关系。该语言仍然是静态类型的,并且
nth_type_t<i, Ts...>;
必须在任何给定的函数示例化中引用一个类型。如果i
可以在for
循环中改变,则这是不可能保证的。该语言要求表达式
i
在用作模板参数时本身是常量表达式,与整个函数体是否只能作为更大常量表达式的一部分求值无关。但i
既不是声明的constexpr
,也不是声明的带有常量初始化器的const
。aiazj4mn2#
虽然这在目前是不可能的,就像the other answer说的那样,但有一个正在进行中的提议可以使这种循环成为可能(我被告知它甚至打算包含在C20中,但不管出于什么原因,它在最后一刻被排除在外)。
这个建议是P1306,目前命名为“扩展语句”,如果幸运的话,它应该包含在C23中。不过,委员会的会议记录只有成员才能看到。