提问人:303 提问时间:11/8/2023 更新时间:11/9/2023 访问量:140
非类型模板参数的无效类型转换
Invalid type conversion of non-type template argument
问:
我希望它可以用作类型的转换常量表达式,因为用户定义的转换运算符。但是,GCC 和 MSVC 拒绝此代码,而 Clang 似乎接受它。根据 C++ 标准,代码应该是合法的吗?x
bool
constexpr operator bool() const
template<bool B>
struct s { constexpr operator bool() const { return B; } };
constexpr auto f(auto x) -> s<x> { return {}; }
static_assert(f(s<true>{})); // clang ok, gcc nope, msvc nope
来自 GCC 的错误消息:
<source>:3:32: error: template argument 1 is invalid
3 | constexpr auto f(auto x) -> s<x> { return {}; }
| ^
<source>:3:32: error: template argument 1 is invalid
<source>:3:32: error: template argument 1 is invalid
<source>:3:32: error: template argument 1 is invalid
<source>:3:29: error: invalid template-id
3 | constexpr auto f(auto x) -> s<x> { return {}; }
| ^
<source>:3:32: error: use of parameter outside function body before '>' token
3 | constexpr auto f(auto x) -> s<x> { return {}; }
| ^
<source>:3:11: error: deduced class type 's' in function return type
3 | constexpr auto f(auto x) -> s<x> { return {}; }
| ^~~~
<source>:2:8: note: 'template<bool B> struct s' declared here
2 | struct s { constexpr operator bool() const { return B; } };
| ^
<source>:4:15: error: 'f' was not declared in this scope
4 | static_assert(f(s<true>{}));
| ^
来自 MSVC 的错误消息:
<source>(4): error C2440: 'static_assert': cannot convert from 's<x>' to 'bool'
<source>(4): note: No user-defined-conversion operator available that can perform
this conversion, or the operator cannot be called
答:
2赞
ecatmur
11/8/2023
#1
根据 GCC 维护者的评论,gcc 的动机是通过对 [basic.scope.param] 的注释来拒绝的:
[注 1:函数参数不能用于 parameter-declaration-clause ([dcl.fct.default]) 中的值。— 结束语]
但是,您没有将参数用于其值(转换运算符不访问类对象),因此此注释无关紧要(当然,也是非规范的)。没有其他拒绝的理由,因此根据 [expr.const]/5,应该接受代码。
如果将声明更改为:f
constexpr auto f(auto x) -> decltype([](auto y) { return s<y>(); }(x)) { return {}; }
然后 gcc 和 MSVC 接受,但 clang 拒绝。
评论
0赞
303
12/9/2023
标准中的哪个特定文本允许使用 ?感兴趣的部分是调用成员函数的地方,而不需要实际的对象来操作。[](auto x) -> decltype(+std::get<x>(std::array{0})) { return {}; }(std::bool_constant<true>{});
x
constexpr operator bool() const
std::bool_constant
0赞
ecatmur
12/13/2023
@303 expr.const/5:“表达式 E 是核心常量表达式,除非 [...]”和示例 5 到 expr.const/8。
评论
return s<x>{};
using return_type = s<x>;