8

我正在测试这段代码(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在编译时就清楚地知道了,因此,据我所知,编译器使用它来实例化模板应该没有任何问题。

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

4

2 回答 2

10

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

consteval函数是或不是这些也无关紧要constexpr

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

该语言要求i用作模板参数的表达式本身是一个常量表达式,与整个函数体是否只能作为更大常量表达式的一部分进行评估无关。但是i既没有声明constexpr,也没有const使用常量初始化器声明。

于 2022-01-29T13:14:10.307 回答
5

虽然目前不可能像其他答案所说的那样,但有一个提案正在编写中,可以使这种循环可以编写。(有人告诉我它甚至打算包含在 C++20 中,但无论出于何种原因,它在最后一刻被遗漏了。)

该提案是P1306,目前命名为“扩展语句”,如果幸运的话,它应该包含在 C++23 中。GitHub上有一个跟踪问题;然而,委员会的程序只有成员才能看到。

于 2022-01-29T14:32:36.037 回答