如果我试着这样做:
template <auto X, auto E>
constexpr decltype(X) const_pow() noexcept
{
return !E ? 1 : 1 == E ? X : (E % 2 ? X : 1) * const_pow<X * X, E / 2>();
}
我得到一个error:
prog.cc: In instantiation of 'constexpr decltype (X) const_pow() [with auto X = 100000000; auto E = 0; decltype (X) = int]':
prog.cc:6:73: recursively required from 'constexpr decltype (X) const_pow() [with auto X = 100; auto E = 1; decltype (X) = int]'
prog.cc:6:73: required from 'constexpr decltype (X) const_pow() [with auto X = 10; auto E = 3; decltype (X) = int]'
prog.cc:11:32: required from here
prog.cc:6:62: warning: integer overflow in expression of type 'int' results in '1874919424' [-Woverflow]
6 | return !E ? 1 : 1 == E ? X : (E % 2 ? X : 1) * const_pow<X * X, E / 2>();
| ~~^~~
prog.cc:6:73: error: no matching function for call to 'const_pow<(100000000 * 100000000), (0 / 2)>()'
解决方法很简单(例如requires
或if constexpr
),但是为什么编译器不自己结束递归呢?
1条答案
按热度按时间tzdcorbm1#
[温度 Jmeter ]/5:
除非函数模板专门化是声明的专门化,否则当专门化在需要函数定义存在的上下文中被引用时,或者如果定义的存在影响程序的语义时,函数模板专门化被隐式示例化。
[基本定义odr]/11:
每个程序应包含至少一个定义的每个函数或变量是odr使用在该程序以外的一个废弃的语句;不需要诊断。
[基本定义odr]/8:
如果一个函数是由一个可能求值的表达式或转换命名的,则该函数是odr-used函数。
[基本.定义.odr]/4.1:
如果函数是重载解析中重载集的选定成员,则该函数由表达式或转换命名,重载解析是作为形成该表达式或转换的一部分而执行的[...]
条件表达式odr-中的调用使用
const_pow<...>
,而不管是否执行分支,从而导致其示例化。