main の最後の行がコンパイルに失敗する理由を知っている人はいますか (失敗するのはコンパイルであることに注意してください):
template <typename TT> inline TT getAs();
template <> string getAs() { return "bye"; }
template <> int getAs() { return 123; }
class Foo
{
public:
template <typename TT>
inline operator TT() const { return ::getAs<TT>(); }
template <typename TT>
inline string getAs() const { return ::getAs<TT>(); }
};
Foo tempFoo() { return Foo(); }
int main()
{
Foo foo;
string testStringLocal = foo; // OK
int testIntTemp = tempFoo(); // OK
string testStringTemp = tempFoo().getAs<string>(); // OK
const string& testStringTemp2 = tempFoo(); // OK
string testStringTemp3 = tempFoo(); //.getAs<string>(); // FAIL!
}
メインの行のコメントで示したように、
- Foo から文字列への暗黙的な変換は、非一時オブジェクト (foo など) で正常にコンパイルされます。
- int(またはlongなど)に変換するときの一時オブジェクトと同様に
- メソッドを介して文字列に変換する場合は正常に機能します
const string&
タイプが文字列の代わりである場合と同様に
VS2010でこれを試しました。上記のコードは 2005 年には問題なくコンパイルされますが、2010 年は正しいと思います。
テンプレート定義と特殊化を削除し、各オーバーロードを明示的に定義するだけで、演算子による文字列への暗黙的な変換は正常に機能します。
class Foo
{
public:
operator string() const { return ::getAs<string>(); }
operator int() const { return ::getAs<int>(); }
...
};
保守性が低いため、この回避策を使用しないことをお勧めします。
main() の最後の行を正常にコンパイルする別の方法を知っている人はいますか? テンプレートが関係しているかどうかに関係なく、複数の変換 (char *、alloc、string) が可能であり、オブジェクトが一時的であるという事実が重要であるように思われるため、Explicit conversion および templated conversion operatorに対する受け入れられた回答はここでは適用されないと思います.
編集:この投稿の元のコードは、クラス内のテンプレートの特殊化を示していました。これは、元のソースから SO のスタンドアロン コードを作成した結果でした (名前空間レベルの特殊化をクラスに移動しましたが、VS2010 は文句を言いませんでした)。問題は専門分野ではありません。投稿されたコードを元のコードに近づけるように変更し (私が行ったように)、クラス内の特殊化を使用しません (もちろん問題はまだあります)。Derek's answer は、VS2010 に固有のものである可能性があることを示しています。