次の 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;
}
アイデアは、 auto...->decltype(expr) を使用して、テンプレート引数推定 (SFINAE) の一部として不適切な形式の式を除外し、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 がここに適用されると仮定するのは間違っていたのかということです。根拠のある回答をいただければ幸いです。
編集:この場合、最初の関数テンプレートを優先するオーバーロードの解決のために、コード
に変更decltype(new T(*ptr))
するとコンパイルされます。T*
しかし、これは式を関数宣言の一部として持つ目的に反します。目的は、エラーが発生した場合に、オーバーロード解決セットからコンパイラーが関数を追い出すようにすることです。