2011-01-28 15 views
6

Iは クローンメンバ関数を使用して(存在する場合)、コピーにバック コンストラクタを落下してオブジェクトを複製しようとした以下のC++ 0Xコードで:不正な形式のC++ 0xコードまたはコンパイラのバグ?

struct use_copy_ctor {}; 
struct prefer_clone_func : use_copy_ctor {}; 

template<class T> 
auto clone(T const* ptr, prefer_clone_func) 
-> decltype(ptr->clone()) 
{ return ptr->clone(); } 

template<class T> 
auto clone(T const* ptr, use_copy_ctor) 
-> decltype(new T(*ptr)) 
{ return new T(*ptr); } 

struct abc { 
    virtual ~abc() {} 
    virtual abc* clone() const =0; 
}; 

struct derived : abc 
{ 
    derived* clone() const { return new derived(*this); } 
}; 

int main() 
{ 
    derived d; 
    abc* p = &d; 
    abc* q = clone(p,prefer_clone_func()); 
    delete q; 
} 

考え自動を使用することですテンプレート型引数の減算(SFINAE)と の一部として、間違った形式の 式を除外するには、 - > decltype(expr)を使用して、両方のクローン関数テンプレートのあいまいさを解決してください。 部分的順序付けwrt第2の関数パラメータ。

残念ながら、GCC 4.5.1は、このプログラムは受け付けていません:

test.cpp: In function 'int main()': 
test.cpp:28:39: error: cannot allocate an object of abstract type 
    'abc' 
test.cpp:14:12: note: because the following virtual functions are 
    pure within 'abc': 
test.cpp:16:16: note:  virtual abc* abc::clone() const 
test.cpp:28:39: error: cannot allocate an object of abstract type 
    'abc' 
test.cpp:14:12: note: since type 'abc' has pure virtual functions 

さて、質問です、これはコンパイラのバグですか、私はSFINAEがここで適用される を負い間違っていましたか?私はしっかりとした推論で答えを感謝します。

編集:私は、コードが原因で、この場合の第1関数テンプレートを好むオーバーロードの解決のコンパイルdecltype(new T(*ptr))T*に変更した場合 。しかしこれは、関数宣言の一部として表現を持つという目的を破るものです。目的は、コンパイラがエラーの場合に設定されたオーバーロード解像度から関数をキックさせることです。

+0

継承が関係しているので、私は「選択」引数を参照することにします。あなたの問題を解決するものではありません... –

+0

@Matthieu:このタグを発送する作業を参照する必要はありません。部分オーダリングオーバーロード解決規則は依然として適用されます。私はこれがコンパイラによってどのように最適化されているかチェックしていませんが、libstdC++は参照なしでタグのディスパッチを使ってstd :: advanceを実装しています。 – sellibitze

+0

私はそれが必須ではないことを知っています、私はまだオブジェクトのスライスを避けるために、(私はタグがデータ/メソッドを持っているとは限りません...) –

答えて

1

これは実際にはコンパイラのバグであり、reportを提出したと私は確信しました。しばらく様子を見てみましょう。回避策としてdecltype(new T(*ptr))T*に置き換えることができます。唯一の違いは、関数テンプレートがこの場合大きな問題ではないオーバーロード分解能セットの一部にとどまることです。

を編集してください:私はclang ++が上記のコードを受け入れると言いました。

1

私はMSVCに非常によく似た問題を抱えていましたが、コンパイラは仮想関数の共変種戻り型を認識しないことが判明しました。 derivedのクローンの定義をabcに変更してみてください。

+0

これは役に立ちません。 'derived'は抽象ではありません。私はmain関数に 'derived'型のオブジェクトを作成します。 – sellibitze

関連する問題