c++ - 为什么递归 constexpr 模板值不编译?

标签 c++ templates c++17 constexpr if-constexpr

我正在使用 C++17 中的递归模板定义一种方法来了解类型在类型列表中的位置。我尝试了两种方法:一种使用 constexpr 值,一种使用 constexpr 函数。第二个,使用 if 语句,编译,而第一个,使用三元运算符,不编译。

#include <type_traits>
#include <iostream>

template<typename Searching, typename First, typename...Others>
constexpr std::size_t index_of = std::is_same_v<Searching,First> ? 0 : 1 + index_of<Searching,Others...>;

template<typename Searching, typename First, typename...Others>
constexpr std::size_t IndexOf() {
    if constexpr(std::is_same_v<Searching,First>)
        return 0;
    else return 1 + IndexOf<Searching,Others...>();
};

int main() {
    std::cout << index_of<int, int> << std::endl; //does not compile
    std::cout << IndexOf<int, int>() << std::endl; //compile
    //both should return 0
    return 0;
}

我的编译器 migw64 说:

wrong number of template arguments (1, should be at least 2)
constexpr std::size_t index_of = std::is_same_v<Searching,First> ? 0 : 1 + index_of<Searching,Others...>;

据我了解,三元运算符需要计算它的两个操作数,因此不能用于此类递归。

我说得对吗?如果是,为什么会这样?
谢谢。

最佳答案

我将从问题的末尾开始,然后继续。

From what I understand, the ternary operator needs to evaluate its two operands

没有。三元(意思是“由三个组成”)运算符有三个操作数,而不是两个。评估此运算符时,将评估三个操作数中的两个:条件和条件选择的操作数。

评估不是你的问题所在。

the first, using ternary operator, does not compile.

我想我明白这是为什么了。您正在将条件运算符的结果分配给 std::size_t .为了编译,这个结果的类型必须是 std::size_t或可转换为该类型。所以编译器需要判断结果的类型。我找到了 rules for determining the type .如果第二个或第三个操作数的类型为 void,则适用第一条规则。 .因此,即使这些操作数之一不会被计算,它们的类型也必须是已知的。

好的,那么你的第三个操作数是什么类型的,那个不会被计算的?嗯,是1 + index_of<int> , 所以我们最好检查 index_of<int> 的声明.糟糕,我们需要两个参数。提示错误消息。

这可能是您无论如何都必须处理的事情,因为在“未找到”的情况下,您应该为任何一种方法得到相同的错误(例如:index_of<unsigned, int, long, float>)。您可能已经注意到,默认错误消息并不能很好地描述出错的地方,因此您的模板专门解决这种情况可能是个好主意,即使解决这种情况只是意味着提供更易于理解的编译器错误。

关于c++ - 为什么递归 constexpr 模板值不编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51004670/

相关文章:

c++ - 我可以使单个模板<typename T> 应用于多个定义/声明吗?

c++ - boost::make_shared 不是在调用(放置)运算符 new 吗?

c++ - 使用模板的动态多态行为?

c++ - 使用 C++ 特化模板时的奇怪行为

c++ - Socket 客户端始终连接到本地主机

c++ - 纹理映射到瓷砖

c++ - 在这种情况下,c++标准是否保证模板实例化?

c++ - 使用 c++17 的弱绑定(bind)

c++ - 我们可以在 noexcept 规范中引用成员变量吗?

c++ - 参数包是否有设定限制?