c++ - 为什么递归 constexpr 模板值无法编译?
问题描述
我正在定义一种方法来了解类型在类型列表中的位置,使用 C++17 中的递归模板。我尝试了两种方法:一种使用 constexpr 值,另一种使用 constexpr 函数。第二个 usingif
语句编译,而第一个 using 三元运算符不编译。
#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 说:
模板参数的数量错误(1,应至少为 2)
constexpr std::size_t index_of = std::is_same_v<Searching,First> ?0 : 1 + index_of<正在搜索,其他...>;
据我了解,三元运算符需要评估它的两个操作数,所以它不能用于这种类型的递归。
我对吗 ?如果是,为什么会这样?
谢谢你。
解决方案
我将从问题的结尾开始,然后继续工作。
据我了解,三元运算符需要评估它的两个操作数
不,三元(意思是“由三个组成”)运算符有三个操作数,而不是两个。评估此运算符时,将评估三个操作数中的两个:条件和条件选择的任何操作数。
评估不是您的问题所在。
第一个,使用三元运算符,不编译。
我想我明白为什么会这样了。您正在将条件运算符的结果分配给 a std::size_t
。为了编译它,这个结果的类型必须是std::size_t
或可转换为该类型。所以编译器需要判断结果的类型。我找到了确定类型的规则。如果第二个或第三个操作数具有 type ,则适用第一条规则void
。因此,即使这些操作数之一不会被评估,它们的两种类型都必须是已知的。
好的,那么你的第三个操作数的类型是什么,不会被评估的那个?嗯,它是1 + index_of<int>
,所以我们最好检查index_of<int>
. 糟糕,我们需要两个参数。提示错误消息。
无论如何,这可能是您必须处理的事情,因为在“未找到”的情况下,您应该对任何一种方法都得到相同的错误(例如:)index_of<unsigned, int, long, float>
。您可能已经注意到,默认错误消息并不能很好地描述发生了什么问题,因此您的模板专门解决这种情况可能是一个好主意,即使解决这种情况只是意味着提供更易于理解的编译器错误。
推荐阅读
- javascript - 使用python获取空白电子邮件
- java - 如何在下面的Java代码中显示正确和错误的答案?
- vb.net - 如何计算多个日期时间文本框
- c++ - Visual Studio 2019 nuget libcurl LNK2019 LNK1120
- scala - 如何将 rdd / 数据框 / 数据集转换为字符串
- htmlunit - HtmlUnit:登录成功后进行ajax调用以获取json数据
- c# - 使用 FastMember 从集合中获取值
- r - 为什么线图没有跟随 ggplot 中的第二个 y 轴?
- android - 滚动结束后使底部按钮出现
- mediawiki - 将 Url 的查询结果格式化为 Semantic MediaWiki 中的给定字符串