带可变参数模板的constexpr最小值函数编译问题咨询
可变参数模板函数中
constexpr if的疑问解析 场景重现
我编写了一个用于查找最小值的可变参数模板函数,以下代码可正常运行:
template<typename T, typename... Ts> T minimumval(const T& a, const T& b, const Ts&... t) { const auto m = a < b ? a : b; if constexpr(sizeof...(t) > 0) { return minimumval(m, t...); } return m; }
但移除constexpr关键字后,会触发编译错误:
<source>:14:26: error: no matching function for call to 'minimumval(const int&)' 14 | return minimumval(m, t...); | ~~~~~~~~~~^~~~~~~~~ <source>:11:3: note: candidate: 'template<class T, class ... Ts> T minimumval(const T&, const T&, const Ts& ...)' 11 | T minimumval(const T& a, const T& b, const Ts&... t) { | ^~~~~~~~~~
此时必须添加单参数的基例函数,代码才能正常运行:
template<typename T> T minimumval(const T& val) { return val; } template<typename T, typename... Ts> T minimumval(const T& a, const T& b, const Ts&... t) { const auto m = a < b ? a : b; if (sizeof...(t) > 0) { return minimumval(m, t...); } return m; }
疑问解答
1. 既然普通if块不会执行,为什么编译器仍要求存在minimumval(const int&)?
C++编译器处理模板函数时,会实例化整个函数体的所有代码,不会因为某个分支在运行时不会走到就跳过检查。
用普通if时,哪怕sizeof...(t) == 0时不会进入if块,但编译器还是会检查minimumval(m, t...)这个调用的合法性——此时t...是空参数包,调用会变成minimumval(m),而代码里没有单参数版本的minimumval,所以就会报找不到匹配函数的错误。
说白了,普通if是运行时分支,模板实例化阶段编译器不会跳过对分支内代码的语法和合法性校验。
2. constexpr在这里起到了什么不同的作用?
constexpr if是编译时分支,核心特性是:编译器在模板实例化阶段,会根据条件的真假,完全丢弃不满足条件的分支代码。
当sizeof...(t) == 0时,if constexpr的条件为假,里面的return minimumval(m, t...);这段代码会被编译器彻底忽略,根本不会去检查这个调用是否合法。只有当sizeof...(t) > 0时,编译器才会处理该分支的函数调用,此时t...至少还有一个参数,调用的是需要两个及以上参数的minimumval模板,自然能匹配成功。
这就是为什么不需要额外的单参数基例函数——不满足条件的分支代码直接被编译器“删掉”了。
内容的提问来源于stack exchange,提问作者stonp
相关产品推荐
相关产品推荐

