繁体   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> {};

在尝试使用static_assert禁用常规模板实例化时,我发现即使在未实例化模板的情况下,上面的clang代码也会生成断言错误,而gcc仅在使用参数42以外的实例化Hitchhiker时才生成断言错误。

摆弄我发现这个断言:

template <int answer> struct Hitchhiker {
  static_assert(sizeof(int[answer]) != sizeof(int[answer]), "Invalid answer");
};

template <> struct Hitchhiker<42> {};

在两个编译器上的行为相同:断言仅在实例化常规模板时才起作用。

标准说什么,哪个编译器正确?

g++ 4.9.2
clang++ 3.50

两种编译器都是正确的。 从[temp.res] / 8:

如果无法为模板生成有效的专业化名称,并且该模板未实例化,则该模板格式错误,无需诊断。

没有可以从主模板Hitchhiker生成的有效专业化名称,因此它Hitchhiker不正确,不需要诊断。 clang选择仍然发出诊断。

如果您只想允许42 ,则只需不定义常规模板:

template <int > struct Hitchhiker;
template <> struct Hitchhiker<42> {};

@TartainLlama找到的报价

如果由于不依赖于模板参数的构造而导致模板定义后的假想实例化格式不正确,则程序格式不正确; 无需诊断。

N4296 [温度] / 8

这在定义了主模板(其中包含static_assert模板)后立即适用。 因此,以后的专业化(针对42 )无法考虑,因为它尚不存在。

下一个问题是static_assert( sizeof(answer) != sizeof(answer), 是否取决于 answer 。从语义上讲,语法上没有,从标准上讲:

在模板内部,某些构造的语义可能因一个实例而异。 这样的构造取决于模板参数。

N4296 [温度深度] / 1

构造sizeof(answer) != sizeof(answer)从一个实例到另一个实例没有不同。 因此,这种构造不依赖于模板参数。 这意味着整个static_assert不依赖于template参数。

因此,您的程序格式错误,不需要诊断。 发出任意诊断(例如static_assert失败)是有效的编译器行为。 缺少问题是有效的编译器行为。 由标准格式未定义的,由错误格式编译的程序的行为:未定义的行为。 允许鼻恶魔。

花哨的尝试(例如sizeof(int[answer])!=sizeof(int[answer])可能会让当前的God编译器满意,但并不能使您的程序结构更合理。

您可能会遇到这样的情况,即编译器不太可能抓住您,但是不管编译器是否能够抓住您,它的格式仍然不正确。 通常,C ++希望保留自身(及其编译器)的自由,以“早于实例化”来查找无效的模板代码。 这意味着模板代码必须产生可能的合法代码。

您可能需要类似=delete的附加消息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM