在不带constexpr的模板非类型参数中进行类型转换 [英] Type conversion at template non-type argument without constexpr
问题描述
请考虑以下代码:
struct A {
constexpr operator int(){return 42; }
};
template< int>
void foo(){}
void bar(A a){
foo< a>();
}
int main(){
foo< A {}>();
const int i = 42;
foo< i>(); //(1)
A a {};
static_assert(i == a,);
bar(a);
foo< a>(); // error here
}
Clang 3.7 with c ++ 14接受这个,而gcc 5.2.0与c ++ 14不会,产生以下消息:
/ tmp / gcc-explorer-compiler1151027-68-1f801jf / example.cpp:在函数'int main()'中:
26:错误:'a'的值在常量表达式中不可用
foo< a>();
^
23:注意:'a'未声明为'constexpr'
A a {};
^
编译失败
gcc修复了gcc编译错误,但没有 constexpr ccc建议的code> a code>,编译器是正确的吗?
对我来说,似乎 a
在常量表达式,如 static_assert
ceritifies。此外, i
可以以相同的方式使用(标记为(1)
), code> bar()编译,也让我认为gcc是错误的。
UPD 报告了针对gcc的错误: https://gcc.gnu.org/bugzilla/show_bug .cgi?id = 68588 //eel.is/c++draft/expr.const#4rel =nofollow> [expr.const] /(4.1),而且我没有看到一个适用的项目符号, a href =http://eel.is/c++draft/expr.const#2 =nofollow> [expr.const] / 2 ,这将阻止您的表达式成为常量表达式。事实上,要求是如此宽松,声明 a
为
A一个;
是仍然给出一个格式良好的程序,即使 a
没有 constexpr
默认构造函数等,因为转换运算符 constexpr
并且没有成员被求值。
正如你所看到的,GCC是矛盾的,因为它允许 static_assert中的
条件,而不是模板参数。 a
Consider the following code:
struct A {
constexpr operator int() { return 42; }
};
template <int>
void foo() {}
void bar(A a) {
foo<a>();
}
int main() {
foo<A{}>();
const int i = 42;
foo<i>(); // (1)
A a{};
static_assert(i == a, "");
bar(a);
foo<a>(); // error here
}
Clang 3.7 with c++14 accepts this, while gcc 5.2.0 with c++14 does not, producing the following message:
/tmp/gcc-explorer-compiler1151027-68-1f801jf/example.cpp: In function 'int main()': 26 : error: the value of 'a' is not usable in a constant expression foo<a>(); ^ 23 : note: 'a' was not declared 'constexpr' A a{}; ^ Compilation failed
Changing a
to be constexpr
as suggested by gcc fixes the gcc compilation error, but without constexpr
, which compiler is right?
For me, it seems that a
should be "usable in constant expression", as static_assert
ceritifies. Moreover, the fact that i
can be used the same way (marked (1)
), and the fact that bar()
compiles, also makes me think that gcc is wrong.
UPD: reported a bug against gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68588
The user-defined conversion is allowed by [expr.const]/(4.1), and I don't see a single applicable bullet point in [expr.const]/2 that would prevent your expression from being a constant one. In fact, the requirements are so loose that declaring a
as
A a;
is still giving a well-formed program, even if a
didn't have a constexpr
default constructor etc., since the conversion operator is constexpr
and no members are evaluated.
As you saw yourself, GCC is contradictory in that it allows a
in the static_assert
condition but not a template-argument.
这篇关于在不带constexpr的模板非类型参数中进行类型转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!