简体   繁体   English

static_assert取决于非类型模板参数(gcc和clang的不同行为)

[英]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.

相关问题 具有非类型模板参数的功能模板中的static_assert - static_assert in function template with non-type template parameter c++ 20中如何静态断言该类型对于模板非类型参数是可行的 - How to static_assert that type is viable for template non-type parameter in c++20 模板功能取决于非类型参数 - Template function dependent on non-type parameter Clang和GCC在铸造C ++ 17中对非类型模板参数的auto说明符不同意 - Clang and GCC disagree in auto specifier for non-type template parameter in a casting C++17 非类型模板参数取决于默认模板类型参数 - Non-type template parameter dependent on a default template type parameter 检查模板参数类型是否被另一个函数接受的static_assert - static_assert that checks if template parameter type is accepted by another function 模板非类型参数具有不同类型 - Template non-type parameter with different types (部分)专门化依赖类型的非类型模板参数 - (Partially) specializing a non-type template parameter of dependent type 自动非类型模板参数:Clang中的模糊部分特化 - Auto non-type template parameter: ambiguous partial specializations in Clang 类模板参数的static_assert - static_assert of class template parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM