[英]static_assert dependent on non-type template parameter (different behavior on gcc and clang)
template <int answer> struct Hitchhiker {
static_assert(sizeof(answer) != sizeof(answer), "Invalid answer");
};
template <> struct Hitchhiker<42> {};
While trying to disable general template instantiation with static_assert
I discovered that the above code in clang
generates the assert error even when the template is not instantiated, while gcc
generates the assert error only when instantiating Hitchhiker
with a parameter other than 42
. 在尝试使用
static_assert
禁用常规模板实例化时,我发现即使在未实例化模板的情况下,上面的clang
代码也会生成断言错误,而gcc
仅在使用参数42
以外的实例化Hitchhiker
时才生成断言错误。
Fiddling around I found that this assert: 摆弄我发现这个断言:
template <int answer> struct Hitchhiker {
static_assert(sizeof(int[answer]) != sizeof(int[answer]), "Invalid answer");
};
template <> struct Hitchhiker<42> {};
behaves the same on both compilers: the assert kicks in only when the general template is instantiated. 在两个编译器上的行为相同:断言仅在实例化常规模板时才起作用。
What does the standard says, which compiler is right? 标准说什么,哪个编译器正确?
g++ 4.9.2
clang++ 3.50
Both compilers are correct. 两种编译器都是正确的。 From [temp.res]/8:
从[temp.res] / 8:
If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.
如果无法为模板生成有效的专业化名称,并且该模板未实例化,则该模板格式错误,无需诊断。
There does not exist a valid specialization that can be generated from the primary template Hitchhiker
, so it is ill-formed, no diagnostic required. 没有可以从主模板
Hitchhiker
生成的有效专业化名称,因此它Hitchhiker
不正确,不需要诊断。 clang chooses to issue a diagnostic anyway. clang选择仍然发出诊断。
If you only want to allow 42
, then simply don't define the general template: 如果您只想允许
42
,则只需不定义常规模板:
template <int > struct Hitchhiker;
template <> struct Hitchhiker<42> {};
Quotes found by @TartainLlama @TartainLlama找到的报价
If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed;
如果由于不依赖于模板参数的构造而导致模板定义后的假想实例化格式不正确,则程序格式不正确; no diagnostic is required.
无需诊断。
N4296 [temp.res]/8 N4296 [温度] / 8
This applies immediately after the primary template is defined (the one with the static_assert
in it). 这在定义了主模板(其中包含
static_assert
模板)后立即适用。 So the later specialization (for 42
) cannot be considered, as it does not exist yet. 因此,以后的专业化(针对
42
)无法考虑,因为它尚不存在。
The next question is if static_assert( sizeof(answer) != sizeof(answer),
depends on answer
. Semantically it does not, syntactically it does, and standard-wise: 下一个问题是
static_assert( sizeof(answer) != sizeof(answer),
是否取决于 answer
。从语义上讲,语法上没有,从标准上讲:
Inside a template, some constructs have semantics which may differ from one instantiation to another.
在模板内部,某些构造的语义可能因一个实例而异。 Such a construct depends on the template parameters.
这样的构造取决于模板参数。
N4296 [temp.dep]/1 N4296 [温度深度] / 1
The construct sizeof(answer) != sizeof(answer)
does not differ from one instantiation to another. 构造
sizeof(answer) != sizeof(answer)
从一个实例到另一个实例没有不同。 So such a construct does not depend on the template parameters. 因此,这种构造不依赖于模板参数。 Which means the entire
static_assert
does not depend on the template parameter. 这意味着整个
static_assert
不依赖于template参数。
Thus your program is ill formed, no diagnostic required. 因此,您的程序格式错误,不需要诊断。 Issuing an arbitrary diagnostic (such as the
static_assert
failing) is valid compiler behavior. 发出任意诊断(例如
static_assert
失败)是有效的编译器行为。 Missing the problem is valid compiler behavior. 缺少问题是有效的编译器行为。 The behavior of a program compiled from an ill formed, no diagnostic required program is not defined by the standard: it is undefined behavior.
由标准格式未定义的,由错误格式编译的程序的行为:未定义的行为。 Nasal demons are permitted.
允许鼻恶魔。
Fancy attempts (like sizeof(int[answer])!=sizeof(int[answer])
may please the current god compiler, but does not make your program more well formed. 花哨的尝试(例如
sizeof(int[answer])!=sizeof(int[answer])
可能会让当前的God编译器满意,但并不能使您的程序结构更合理。
You could make a case where the compiler is unlikely to be able to catch you at it, but the ill-formed-ness remains regardless of the ability for the compiler to catch you with it. 您可能会遇到这样的情况,即编译器不太可能抓住您,但是不管编译器是否能够抓住您,它的格式仍然不正确。 As a general rule, C++ wants to leave itself (and its compilers) freedom to find invalid template code "earlier than instantiation";
通常,C ++希望保留自身(及其编译器)的自由,以“早于实例化”来查找无效的模板代码。 this means that template code must produce possibly legal code.
这意味着模板代码必须产生可能的合法代码。
It is possible you want something like =delete
with a message attached. 您可能需要类似
=delete
的附加消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.