2011-12-13 16 views
7

自分の型消去イテレータに取り組んでいる間、私は、コンパイラ(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が2フェーズルックアップを実装していると聞きましたが、これは関連性があると思われますが、frombaseから継承する行を削除すると、なぜコンパイルされるのか説明しません。 誰でもMSVC10がこれをコンパイルしない理由を教えてもらえますか?私は避けなければならないことは何をしたのですか?

+0

、GCC 4.6は問題なくお使いのサンプルコードをコンパイルする(Linux/Debianの/シド/ AMD64上)。おそらく、あなたはGCCに切り替えることができます(例えばMinGWやCygwinのいくつかの亜種...)? –

+0

私は実際にIDEOne経由でかなりの量のデバッグを行いましたが、私のコマンドライン-fuとlinuxは弱いので、Cygwinは威圧しています。私はそれでもおもちゃを始めます。 –

+0

あなたは自分自身から継承するテンプレートクラスを持っていますか?または私はこれを間違って読んでいますか?それはAJG85 @最新のC++標準準拠... – AJG85

答えて

1

を:

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;} 
+0

ハァッ、それがなぜ機能するのだろうか。良い発見。 –

1

まあ、私はあきらめたが、私は警告を生成するために管理しました:category = voidで未分化anyの間に追加のクラスと専門の導入を検討し、対応策として

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; 
} 
+0

私のコードには3つのテンプレートクラスがあり、 'Test'は' Whatever 'と無関係なクラスのみを継承しています。 'Test'は' Whatever 'から継承しません。私は継承の順序を逆にしようとし、それが何かを修正するかどうかを見てみましょう。 –

+0

'Whatever 'の継承を元に戻し、関係のない型は問題を解決しません。あなたのコードと私の実際の違いはわかりません... –

+0

私はクラスの名前を変更し、それぞれのクラスが必要な理由とそのパーツの仕組みを少し明確にするためにクラスを再構成しました。 –

1

最も簡単な回避策:交換してください:

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

とは:それは価値がある何のため

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

これは正しいことをまったくしないことを除いて。 – Xeo

+0

@ Xeo:実際には...動作するようです...私は検証するためにメンバー関数を追加しました。 WTF? Good find ... –

+0

@Mooing: 'void'の場合でもテンプレートパラメータを切り替える必要があるので、これを行うべきではありません。 – Xeo

関連する問題