3

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 に固有のものである可能性があることを示しています。

4

1 に答える 1

3

Visual C++ 2010 (バージョン 9.0 だと思います) については知りませんが、クラス自体でテンプレート化されたメンバー関数を特殊化することはできません。このコードを提供した最新のコンパイラによって出力されるエラーによると、名前空間スコープで実行する必要があります。

そう、

#include <string>
using namespace std;

class Foo
{
public:
    template <typename TT> inline operator TT()     const;
    template <typename TT> inline TT       getAs()  const;
};

template <>  inline Foo::operator string() const { return "hi"; }
template <>  inline Foo::operator int()    const { return 123; }
template <>  inline string Foo::getAs()  const { return "bye"; }

Foo tempFoo() { return Foo(); }

int main()
{
    Foo foo;
    string testStringLocal = foo;       // OK
    int testIntTemp = tempFoo();        // OK
    string testStringTemp = tempFoo().getAs<string>();  // OK

    string testStringTemp2 = tempFoo();  // OK!
}

Visual C++ 12.0 および g++ 4.7.2 で正常にコンパイルされます。

于 2014-01-03T06:27:26.940 に答える