C++模板递归双链表误差GCC(但铛++接受)

问题描述:

此示例代码:C++模板递归双链表误差GCC(但铛++接受)

#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++ -std=c++11 -DUPPER_LIMIT=100 -ftemplate-depth=500 -o test main.cpp 
> ./test 
0 
1 
2 
100 
99 
98 
-1 

代码中有错吗?我不知道海湾合作委员会想超越UPPER_LIMIT,因为有一个终止专业化。

+2

可能是因为您在定义“Wrapper ”专业化之前为'Wrapper '定义了静态成员变量。如果你定义了所有的'Wrapper'结构,那么会发生什么?然后是这些类的静态结构? – 1201ProgramAlarm

+0

@ 1201ProgramAlarm你在正确的轨道上,但它是静态成员的*定义*,而不是他们的声明导致问题(可能) – Frank

+0

谢谢! - 对你们双方都有同样的意见,回答如下 –

Wrapper<-1>被实例化该线路上

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

这导致Wrapper<0>被实例化,这会导致Wrapper<1>被实例化,等等。在代码中的这一点上,对于Wrapper<UPPER_LIMIT>专业化尚未定义,所以这会导致无限递归。

Wrapper<UPPER_LIMIT>专业化的定义移动到Wrapper<-1>::_nxt定义之上解决了该问题。

显然Clang推迟实例化,以避免出现此问题。

+0

非常感谢! 我也将类声明分隔为* .h –