c++ 为什么我们不能在consteval函数中使用编译时的“变量”作为模板参数?

8nuwlpux  于 2023-03-05  发布在  其他
关注(0)|答案(2)|浏览(102)

我正在测试此代码(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 版本进行了测试,结果相同。

8dtrkrch

8dtrkrch1#

i的值在抽象意义上是已知的时,i保证只在编译时求值并不重要。
函数是consteval还是constexpr或者都不是也没有关系。
该语言仍然是静态类型的,并且nth_type_t<i, Ts...>;必须在任何给定的函数示例化中引用一个类型。如果i可以在for循环中改变,则这是不可能保证的。
该语言要求表达式i在用作模板参数时本身是常量表达式,与整个函数体是否只能作为更大常量表达式的一部分求值无关。但i既不是声明的constexpr,也不是声明的带有常量初始化器的const

aiazj4mn

aiazj4mn2#

虽然这在目前是不可能的,就像the other answer说的那样,但有一个正在进行中的提议可以使这种循环成为可能(我被告知它甚至打算包含在C20中,但不管出于什么原因,它在最后一刻被排除在外)。
这个建议是P1306,目前命名为“扩展语句”,如果幸运的话,它应该包含在C
23中。不过,委员会的会议记录只有成员才能看到。

相关问题