模板专门化的不同编译器行为

Dmytro Dadyk

在尝试专门化模板时,我发现了不同的编译器行为。这是说明问题的最少代码:

#include <iostream>

template<typename A, typename B>
struct foo {
   static const bool value = false;
};

template<typename B>
struct foo<int, B> {
   static const bool value = !foo<B, B>::value;
};

int main() {
   std::cout << foo<int, int>::value << std::endl;
   return 0;
}

我有带两个参数的通用模板和第一个int参数的专用模板当使用g ++编译器时,我得到

main.cpp: In instantiation of 'const bool foo<int, int>::value':
main.cpp:10:30:   recursively required from 'const bool foo<int, int>::value' 
main.cpp:10:30:   required from 'const bool foo<int, int>::value'
main.cpp:14:32:   required from here 
main.cpp:10:30: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
    static const bool value = !foo<B, B>::value;

因为value获得了从专用版本使用的编译器,并且获得了无限递归。我懂了

Error   C2131   expression did not evaluate to a constant
Error   C2065   'value': undeclared identifier  

用于MSVC。但是使用clang或zapcc,代码可以正确编译。是什么原因?在这种情况下,根据标准,正确的行为是什么?行为是否未定义?

刺柏

我不是语言律师,但这应该汇编。您正在尝试在编译时使用其自身初始化值。我猜这是一个clang错误。实际上,我不明白为什么GCC遇到循环时为什么要遵循这样的递归路径。

顺便一句,MSVC告诉您(GodBolt):

<source>(14): note: see reference to class template instantiation 'foo<int,int>' being compiled

这是正确的收获。MSVC一次胜过其他编译器... :-P

编辑: @aschepler指出,即使没有模板,我们也会获得(GodBolt)相同的行为:

struct bar { static const bool value = !bar::value; };

另一个编辑:似乎直到几年前,由于“语言律师诡辩”,这还是一种有效的代码。您会看到,过去所说的标准(第6.6.2节[basic.start.static]第2段):

具有静态存储持续时间的变量...应零初始化...在进行任何其他初始化之前。

clang认为这意味着您首先要对所有内容进行零初始化,然后再考虑静态持续时间初始化-这意味着bar::value隐式地decltype(bar::value) { 0 }先于其自己的显式初始化。缺陷报告2026之后对此进行了更改

指出这一点的功劳是理查德·史密斯Richard Smith)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

模板构造器中的模板类专门化

来自分类Dev

模板构造器中的模板类专门化

来自分类Dev

Clang无法在模板类专门化中编译模板函数,该模板类专业化具有与模板声明不同的返回类型

来自分类Dev

Clang无法在模板类专门化中编译模板函数,该模板类专业化具有与模板声明不同的返回类型

来自分类Dev

模板专门化和实例化

来自分类Dev

部分专门化具有不同模板参数的模板的模板类

来自分类Dev

如何专门化模板子类?

来自分类Dev

模板专门化中的double template <>

来自分类Dev

如何专门化模板成员函数?

来自分类Dev

使用指令专门化的模板

来自分类Dev

模板成员变量专门化

来自分类Dev

模板成员函数专门化

来自分类Dev

模板类-成员函数专门化

来自分类Dev

部分模板专门化的意外结果

来自分类Dev

C ++:数组的功能模板专门化

来自分类Dev

模板类-成员函数专门化

来自分类Dev

C ++模板类对于不同的编译器的行为有所不同

来自分类Dev

C ++ 11的不同编译器行为

来自分类Dev

在模板专门化中强制发生编译时错误

来自分类Dev

在msvc而非其他上编译的模板成员函数专门化的情况

来自分类Dev

在msvc而非其他上编译的模板成员函数专门化的情况

来自分类Dev

在模板化类中专门化模板化结构

来自分类Dev

将两种不同类型的模板定义专门化

来自分类Dev

如何使用模板模板参数专门化类模板?

来自分类Dev

使用类模板的内部类模板专门化模板

来自分类Dev

使用类型特征专门化字符串迭代器的模板功能

来自分类Dev

显式模板专门化不能具有存储类-成员方法专门化

来自分类Dev

如何使用模板临时参数专门化模板

来自分类Dev

非模板类方法的条件模板专门化

Related 相关文章

  1. 1

    模板构造器中的模板类专门化

  2. 2

    模板构造器中的模板类专门化

  3. 3

    Clang无法在模板类专门化中编译模板函数,该模板类专业化具有与模板声明不同的返回类型

  4. 4

    Clang无法在模板类专门化中编译模板函数,该模板类专业化具有与模板声明不同的返回类型

  5. 5

    模板专门化和实例化

  6. 6

    部分专门化具有不同模板参数的模板的模板类

  7. 7

    如何专门化模板子类?

  8. 8

    模板专门化中的double template <>

  9. 9

    如何专门化模板成员函数?

  10. 10

    使用指令专门化的模板

  11. 11

    模板成员变量专门化

  12. 12

    模板成员函数专门化

  13. 13

    模板类-成员函数专门化

  14. 14

    部分模板专门化的意外结果

  15. 15

    C ++:数组的功能模板专门化

  16. 16

    模板类-成员函数专门化

  17. 17

    C ++模板类对于不同的编译器的行为有所不同

  18. 18

    C ++ 11的不同编译器行为

  19. 19

    在模板专门化中强制发生编译时错误

  20. 20

    在msvc而非其他上编译的模板成员函数专门化的情况

  21. 21

    在msvc而非其他上编译的模板成员函数专门化的情况

  22. 22

    在模板化类中专门化模板化结构

  23. 23

    将两种不同类型的模板定义专门化

  24. 24

    如何使用模板模板参数专门化类模板?

  25. 25

    使用类模板的内部类模板专门化模板

  26. 26

    使用类型特征专门化字符串迭代器的模板功能

  27. 27

    显式模板专门化不能具有存储类-成员方法专门化

  28. 28

    如何使用模板临时参数专门化模板

  29. 29

    非模板类方法的条件模板专门化

热门标签

归档