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

ron*_*ldo 8 c++ templates metaprogramming c++20 consteval

我正在测试这段代码(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);
    }
};
Run Code Online (Sandbox Code Playgroud)

我很困惑它不起作用。GCC 和 clang 同意i不作为常量表达式,因此他们拒绝让我将其作为模板参数传递。然而,i在编译时是清楚的,因此,根据我有限的理解,编译器使用它来实例化模板应该没有任何问题。

这有什么理由不起作用吗?将来有用吗?我已经用两个编译器的主干版本进行了测试,结果相同。

use*_*522 11

i当它的值在抽象意义上已知时,保证仅在编译时进行评估并不重要。

consteval该函数是否constexpr属于这些功能也并不重要。

该语言仍然是静态类型的,并且nth_type_t<i, Ts...>;必须在函数的任何给定实例中引用确切的一种类型。如果i可以在循环中改变for,那是不可能保证的。

该语言要求i用作模板参数的表达式本身就是一个常量表达式,无论整个函数体是否只能作为较大常量表达式的一部分进行计算。但i既没有声明constexpr,也没有const用常量初始值设定项声明。


use*_*170 7

虽然这目前不可能像其他答案所说的那样,但正在研究中的一个提案可以使这种循环的编写成为可能。(我听说它甚至本来应该包含在 C++20 中,但无论出于何种原因,它在最后一刻被遗漏了。)

\n

该提案为P1306,当前名为 \xe2\x80\x98Expansion statements\xe2\x80\x99,如果幸运的话,它应该包含在 C++23 中GitHub 上存在跟踪问题;然而,委员会的会议记录仅对成员可见。

\n