gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:36:41 27 4
gpt4 key购买 nike

此示例代码:

#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> 的特化尚未定义,因此这会导致无限递归。

移动 Wrapper<UPPER_LIMIT> 的定义Wrapper<-1>::_nxt 以上的特化定义解决了问题。

显然 Clang 推迟了实例化,所以这个问题不会出现。

关于c++模板递归双链表错误gcc(但clang++接受),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44988345/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com