4

Visual Studio 2010でコンパイルして正常に動作するさまざまなタイプを取得および設定するために、関数テンプレートの特殊化を使用するバリアントクラスがあります。ただし、このコードは、redhat、ubuntuなどでコンパイルする必要がある一般的なソリューションにありました.

非名前空間スコープでの明示的な特殊化の行に沿ってエラーを受け取りました。簡単な修正は、同じ名前空間内のクラスのスコープ修飾子を使用して、クラスの外部で特殊化を定義することであると考えました。

ただし、さまざまな型から変換するためのクラスの他のメソッドがクラス内でこのテンプレートを使用しているため、インスタンス化後に特殊化が発生するというエラーが発生しています。

したがって、次のようなことを行う正しい方法は何ですか:

namespace Example
{
    class CSomeVariant
    {
    public:
        bool toString(std::string& out)
        {
            return get(out);
        }
    private:
        template <typename T>
        bool get(T& val)
        {
            try {
                val = boost::any_cast<T>(m_stored);
            }
            catch (...) {
                return false;
            }
            return true;
        }

        boost::any m_stored;
    };

    template<>
    bool CSomeVariant::get(std::string& val)
    {
        try {
            if (m_stored.type() != typeid(std::string))
               val = convertToString();
            else
               val = boost::any_cast<std::string>(m_stored);
        }
        catch(...) {
            return false;
        }
        return true;
    }
}

注: これは実際のコードではありませんが、問題を示していると思います。

4

1 に答える 1

3

問題はget()、クラス定義で関数を使用し、後で特殊化することです。これは許可されていません。14.7.3パラグラフ6から

テンプレート、メンバー テンプレート、またはクラス テンプレートのメンバーが明示的に特殊化されている場合、その特殊化は、そのような使用が発生するすべての翻訳単位で、暗黙的なインスタンス化を発生させる特殊化の最初の使用の前に宣言する必要があります。 ; 診断は必要ありません。プログラムが明示的な特殊化の定義を提供しておらず、特殊化が暗黙的なインスタンス化を発生させるような方法で使用されているか、メンバーが仮想メンバー関数である場合、プログラムは不正な形式であり、診断は必要ありません。

解決策の 1 つは、クラス定義を並べ替えて、使用する前に特殊化が宣言されるようにすることです。この場合、特殊化の後まで関数のインライン使用を移動することができました。

#include <string>
#include <boost/any.hpp>
namespace Example
{
    class CSomeVariant
    {
    public:
        bool toString(std::string& out);

    private:
       template <typename T>
       bool get(T& val)
       {
           try {
              val = boost::any_cast<T>(m_stored);
           }
           catch (...) {
               return false;
           }
           return true;
       }

       boost::any m_stored;
   };

   template<>
   bool CSomeVariant::get(std::string& val)
   {
       try {
           if (m_stored.type() != typeid(std::string))
              val = convertToString();
           else
              val = boost::any_cast<std::string>(m_stored);
       }
       catch(...) {
           return false;
       }
       return true;
   }


   inline bool CSomeVariant::toString(std::string& out)
   {
        return get(out);
   }
}
于 2012-05-03T20:19:43.727 に答える