【问题标题】:compiler stack overflow on template code模板代码上的编译器堆栈溢出
【发布时间】:2012-01-19 17:29:16
【问题描述】:

在处理我自己的类型擦除迭代器时,我遇到了一个问题,即编译器 (MSVC10) 因此代码上的堆栈溢出而崩溃:

struct base {};  //In actual code, this is a template struct that holds data
template<class category, class valuetype>  
    struct any;  //In actual code, this is abstract base struct
template<class basetype, class category, class valuetype> 
    struct from; //In actual code, this is function definitions of any

template<class valuetype>
struct any<void,valuetype>
{ void a() {} };
template<class category, class valuetype>  
struct any
    : public any<void,valuetype> //commenting this line makes it compile
{ void b() {} };        

template<class basetype, class valuetype>
struct from<basetype,void,valuetype>
    : public base  //commenting out _either_ of these makes it compile
    , public any<void,valuetype>
{ void c() {} };

int main() {
    from<int, void, char> a;
    a.a();
    a.c();
    any<int, char> b;
    b.a();
    b.b();
    return 0;
}

很明显,我已经删除了所有可能存在错误的地方。 (原始代码是 780+ 行)删除任何剩余的模板参数会导致代码编译。

完整的错误信息是:

main.cpp(23): fatal error C1063: compiler limit : compiler stack overflow
    main.cpp(20) : see reference to class template instantiation 'from<basetype,void,valuetype>' being compiled

IDEOne compiles it fine。我听说 MSVC 实现了错误的两阶段查找,这似乎很相关,但没有解释为什么当我删除使 from 继承自 base 的行时它会编译。 谁能教我为什么 MSVC10 不能编译这个?我做了什么我应该避免的事情?

【问题讨论】:

  • 不管怎样,GCC 4.6 编译您的示例代码没有任何问题(在 Linux/Debian/Sid/AMD64 上)。也许你可以切换到 GCC(例如一些 MinGW 或 Cygwin 变体......)?
  • 我实际上通过 IDEOne 进行了相当多的调试,但是我的命令行 fu 和 linux 很弱,所以 Cygwin 很吓人。不过我开始玩弄它了。
  • 你有一个继承自自身的模板类?还是我读错了?
  • 确保获得 GCC 4.6,因为它在符合最新的 C++ 标准方面取得了很大进展...

标签: c++ templates visual-c++ visual-c++-2010


【解决方案1】:

作为一种解决方法,请考虑在非专业化 any 和专业化 category = void 之间引入一个额外的类:

template <class valuetype>
class detail_void_any
    : public any<void, valuetype>
{
};


template<class category, class valuetype>
class any
    : public detail_void_any<valuetype>
{
};

下面的完整程序应该可以正常编译:

class base {};      // Data Holder (in reality it's templated, so required)
template<class category, class valuetype>  
        class any;  // Virtual Function Interface
template<class basetype, class category, class valuetype> 
        class from; // Virtual Function Implementation

template<class valuetype>
class any<void,valuetype>
{};


template <class valuetype>
class detail_void_any
    : public any<void, valuetype>
{
};

template<class category, class valuetype>
class any
    : public detail_void_any<valuetype>
{
};

template<class basetype, class valuetype>
class from<basetype,void,valuetype>
        : public base  //commenting out _either_ of these makes it compile
        , public any<void,valuetype>
{}; //this is line 23, where the compiler crashes

int main() {return 0;}

【讨论】:

    【解决方案2】:

    好吧,我放弃了,但我确实设法产生了警告:

    template <typename T1, typename T2>
    class Any; // forward
    
    template <typename T2>
    class Any<void, T2> // partial spec of forward
    {};
    
    template <typename T1, typename T2>
    class Any: // template definition
        public Any<void, T2> // inherit from partial spec
    {};
    
    template <typename T1, typename T2>
    class From :
        public Any<int, T2>, // inherit definition
        public Any<void, T2> // inherit definition or partial spec?
        // with spec first we get fatal error C1063: compiler limit : compiler stack overflow (CRASH!)
        // with definition first we get warning C4584: 'From<T1,T2>' : base-class 'Any<void,T2>' is already a base-class of 'Any<int,T2>'
    {};
    
    int main()
    {
        return 0;
    }
    

    【讨论】:

    • 请注意,我的代码有三个模板类,Test 只继承自Whatever&lt;void&gt; 和一个不相关的类。 Test 不继承自 Whatever&lt;int&gt;。不过,我会尝试颠倒继承顺序,看看是否能解决任何问题。
    • 反转Whatever&lt;void&gt; 的继承和不相关的类型并不能解决问题。我看不出你的代码和我的代码有什么真正的区别......
    • 我已经重命名了这些类并重新排列它们,以便更清楚地说明为什么需要每个类以及这些部分是如何工作的。
    • 是的,这可能只是一个稍微精简的复制品,因为我找不到适用于 VS2010 的语法并且我在 SP1 上。如果非专业模板不是它崩溃的第一个基类,则问题似乎是。如果您还没有,您可能想将此发送给 Microsoft,我很想知道他们对此有何评论。
    【解决方案3】:

    最简单的解决方法:替换:

    template<class category, class valuetype>
    class any : public any<void, valuetype>
    {
    };
    

    与:

    template<class valuetype, class category>
    class any : public any<void, valuetype>
    {
    };
    

    【讨论】:

    • @Xeo:其实...它似乎工作...我添加了成员​​函数来验证。怎么回事?很好的发现...
    • @Mooing:不应该这样做,因为您还需要为void 案例切换模板参数。
    • @Xeo:啊,对,我的小测试没有验证它是无效的类别。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-09
    • 2012-08-14
    • 1970-01-01
    • 2015-01-07
    相关资源
    最近更新 更多