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,因为有一个终止专业化。
答
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 –
可能是因为您在定义“Wrapper”专业化之前为'Wrapper '定义了静态成员变量。如果你定义了所有的'Wrapper'结构,那么会发生什么?然后是这些类的静态结构? –
1201ProgramAlarm
@ 1201ProgramAlarm你在正确的轨道上,但它是静态成员的*定义*,而不是他们的声明导致问题(可能) – Frank
谢谢! - 对你们双方都有同样的意见,回答如下 –