c ++模板递归双链表错误gcc(但clang ++接受)

弗兰克·贝格曼

此示例代码:

#include <string>
#include <iostream>

template <int i>
struct Wrapper
{
    static const std::string _str;
    typedef const Wrapper<i+1> NextType_t; // template recursion
    static NextType_t _nxt;
    typedef const Wrapper<i-1> PrevType_t; // template recursion
    static PrevType_t _prev;
};

template<int i>
const std::string Wrapper<i>::_str = std::to_string(i);

template<int i>
typename Wrapper<i>::NextType_t Wrapper<i>::_nxt;

template<int i>
typename Wrapper<i>::PrevType_t Wrapper<i>::_prev;


// recursion termination - lower bound
template <>
struct Wrapper<-1>
{
        static const std::string _str;
        typedef const Wrapper<0> NextType_t;
        static NextType_t _nxt; 
        typedef const Wrapper<-1> PrevType_t;
        static PrevType_t _prev;
};

const std::string Wrapper<-1>::_str = std::to_string(-1);

typename Wrapper<-1>::NextType_t Wrapper<-1>::_nxt;
typename Wrapper<-1>::PrevType_t Wrapper<-1>::_prev;

// recursion termination - upper bound 
template <>
struct Wrapper<UPPER_LIMIT>
{
    static const std::string _str;
    typedef const Wrapper<-1> NextType_t;
    static NextType_t _nxt;
    typedef const Wrapper<UPPER_LIMIT-1> PrevType_t;
    static PrevType_t _prev;
};

const std::string Wrapper<UPPER_LIMIT>::_str = std::to_string(UPPER_LIMIT);

typename Wrapper<UPPER_LIMIT>::NextType_t Wrapper<UPPER_LIMIT>::_nxt;
typename Wrapper<UPPER_LIMIT>::PrevType_t Wrapper<UPPER_LIMIT>::_prev;


int
main(
    int argc,
    char **)
{
    Wrapper<0> wrapperFirst;
    Wrapper<UPPER_LIMIT> wrapperLast;

    // here's the list
    std::cout << wrapperFirst._str << std::endl;
    std::cout << wrapperFirst._nxt._str << std::endl;
    std::cout << wrapperFirst._nxt._nxt._str << std::endl;
    // [...]

    // and the final element
    std::cout << wrapperLast._str << std::endl;
    std::cout << wrapperLast._prev._str << std::endl;
    std::cout << wrapperLast._prev._prev._str << std::endl;
    // [...]

    // and the tailing NIL 
    std::cout << Wrapper<UPPER_LIMIT>::NextType_t::_str << std::endl;

    return 0;
}

对于gcc失败:

> g++ -std=c++11 -DUPPER_LIMIT=100 -ftemplate-depth=500 -o test main.cpp
main.cpp: In instantiation of ‘struct Wrapper<499>’:
main.cpp:24:33:   recursively required from ‘struct Wrapper<1>’
main.cpp:24:33:   required from ‘struct Wrapper<0>’
main.cpp:43:47:   required from here
main.cpp:24:33: fatal error: template instantiation depth exceeds maximum of 500 (use -ftemplate-depth= to increase the maximum)
 typename Wrapper<i>::NextType_t Wrapper<i>::_nxt;
                             ^~~~~~~~~~
compilation terminated.

但对clang成功:

> clang++ -std=c++11 -DUPPER_LIMIT=100 -ftemplate-depth=500 -o test main.cpp
> ./test
0
1
2
100
99
98
-1

代码有问题吗?我想知道gcc是否想超越UPPER_LIMIT,因为这有一个终止的专业化。

沃恩·卡托

Wrapper<-1> 在这条线上实例化

typename Wrapper<-1>::NextType_t Wrapper<-1>::_nxt;

这导致Wrapper<0>实例化,导致Wrapper<1>实例化,等等。在代码的那一点上,Wrapper<UPPER_LIMIT>尚未定义for的专业化,因此这导致了无限递归。

Wrapper<UPPER_LIMIT>专业化的Wrapper<-1>::_nxt定义移到定义之上可以解决此问题。

显然,Clang推迟了实例化,因此不会出现此问题。

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

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

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

仅接受某些类型的C ++模板

c ++如何接受忽略错误数据的输入?

如何在C编程中使用双链表接受字符串?

为什么C ++模板接受数组不比一个接受指针(bis)更专业?

C ++ Eigen:接受任何矩阵类的递归函数

C ++概念的通配符说“为此模板参数接受任何内容”

使用Cython包装C ++模板以接受任何numpy数组

接受const和非const类型的C ++模板类

使用接受回调的模板函数设置C样式数组

C ++模板仅接受具有某些成员的类型名

C++ 模板函数以随机顺序接受参数

C ++复制构造函数错误地接受了参数

C ++错误号分配-是否有接受的标准?

模板接受const但不接受文字

useradd/usermod 不接受 -c

接受 udp 选择错误

链表不接受下一个元素(C 语言)

如何在 ASPX C# 网站的文本框中接受双精度值?

接受模板类的模板函数

调用删除函数后双链表不接受输入

重载[]和=运算符以接受C ++中我的模板类的值

为什么 C++ 可变参数模板不接受 iostream 值作为参数?

如何在C ++ 11中仅接受数字和字符串在模板中?

C ++ 14自动lambda可以接受Obj <std :: tuple <void>>-但是模板函数不能吗?

C ++ Typeid模板值转换为并集没有可接受的转换

C ++接受函数作为模板以及函数返回类型的返回向量

如何防止在C中出现段错误(当接受错误类型的参数时)

C++ 链表错误:获取右值地址 [-fpermissive]

接受 char* 的模板化函数