使用函数参数作为常量表达式模板参数:哪个编译器正确?
模板实参推导与常量表达式的编译器正确性分析
以下是你提供的代码:
template <int V> struct Constant { constexpr operator int() const noexcept { return V; } }; template <class T, int N> struct Array { }; auto function(auto s) -> Array<int, s + s> { return {}; } auto const a = function(Constant<3>{});
Clang的处理是正确的,原因如下:
- 调用
function(Constant<3>{})时,函数参数s的类型被推导为Constant<3>。 - 当
s + s作为非类型模板参数N的实参时,C++标准要求该表达式必须是常量表达式。 Constant<3>的转换运算符operator int()是constexpr修饰的,在常量表达式求值的上下文里,编译器可以合法调用这个转换运算符,将s转换为int类型的常量3,因此s + s的计算结果为6,完全满足非类型模板参数对常量表达式的要求。
其他编译器(如GCC、MSVC)不接受这段代码,是因为它们对常量表达式中隐式转换的判定逻辑更严格,但这不符合C++标准的规定——只要转换操作本身是constexpr,且求值过程中所有操作数都属于常量表达式范畴,这种转换就应当被允许。这里Constant<3>{}是常量表达式对象,调用其constexpr转换运算符的结果也是常量表达式,所以整个s + s表达式符合非类型模板参数的要求。
内容的提问来源于stack exchange,提问作者Guillaume Racicot
相关产品推荐
相关产品推荐

