1

私は一種のシリアル化クラスを書いています。コンテナの機能を提供する必要があります。現在の実装は次のとおりです。

template <typename InsertIter>
bool readContainer(InsertIter result)
{
    typedef typename InsertIter::container_type::value_type tVal;
    UInt32 size = 0;

    if (!read(size))
        return false;

    for (UInt32 i = 0; i < size; ++i)
    {
        tVal val;
        if (!read(val))
            return false;
        *result++ = val;
    }
    return true;
}

template <typename InsertIter>
bool readMap(InsertIter result)
{
    typedef typename InsertIter::container_type::key_type tKey;
    typedef typename InsertIter::container_type::mapped_type tVal;
    UInt32 size = 0;

    if (!read(size))
        return false;

    for (UInt32 i = 0; i < size; ++i)
    {
        std::pair<tKey, tVal> pair;
        if (!read(pair))
            return false;
        *result++ = pair;
    }
    return true;
}

ご覧のとおり、マップのようなタイプ(std::map)やその他のコンテナに対して異なる実装を作成する必要があります。これはであるため、でstd::map::value_typestd::pair(const K, V)ないためですstd::pair(K, V)

そこで、適切なまたはread(InsertIter)を自動的に選択するメソッドを作成したいと思います。これは可能ですか?readContainer(InsertIter)readMap(InsertIter)

4

2 に答える 2

0

私は非常に似たようなことをする例を持っています、そしてあなたがあなたが必要とする何かに変換することはあなたにとって非常に簡単であるはずです:

#include <iostream>

template< typename T >
struct A;

template<>
struct A< int >
{
    void foo() const
    {
        std::cout<<"A(int)::foo()"<<std::endl;
    }
};
template<>
struct A< float >
{
    void foo() const
    {
        std::cout<<"A(float)::foo()"<<std::endl;
    }
};

template< typename T >
void call( const A<T> &a)
{
    a.foo();
}

struct B
{
    template<typename T>
    void bar(const A<T> &a)
    {
        call(a);
    }
};

int main()
{
    A<int> a1;
    A<float> a2;

    B b;
    b.bar(a1);
    b.bar(a2);
}

適切な名前を付け、上記の例では適切なコンテナタイプに置き換えint、必要な機能を実装する必要があります。float

于 2012-07-15T21:14:07.077 に答える
0

私は自分の問題をうまく解決しました。

Johan Lundberg、特にnmに感謝します-私はSFINAEイディオムに精通していなかったので、あなたのリンクとサンプルは私を大いに助けてくれました。

C ++ 11の機能(プロジェクトの詳細)を使用できませんでしたが、必要ありません。

現在のコードは次のようになります。

struct SFINAE
{
    typedef char __one;
    typedef struct { char __arr[2]; } __two;
};

template <typename T> 
class has_mapped_type : public SFINAE
{
    template <typename C> static __one test(typename C::mapped_type *);
    template <typename C> static __two test(...);
public:
    enum { value = (sizeof(test<T>(0)) == sizeof(__one)) };
};

class Serializer
{
    template <typename InsertIter>
    bool read(InsertIter result) const
    {
        return readContainerSelector< InsertIter, 
            has_mapped_type<typename InsertIter::container_type>::value
            > ::read(result, *this);
    }

    template <typename InsertIter, bool isMapType>
    struct readContainerSelector;

    template <typename InsertIter>
    struct readContainerSelector<InsertIter, true>
    {
        static bool read(InsertIter result, Serializer const& ser)
        {
            return ser.readMap(result);
        }
    };

    template <typename InsertIter>
    struct readContainerSelector<InsertIter, false>
    {
        static bool read(InsertIter result, Serializer const& ser)
        {
            return ser.readContainer(result);
        }
    };

    // methods from my topic post
    template <typename InsertIter> bool readContainer(InsertIter result);
    template <typename InsertIter> bool readMap(InsertIter result)

};
于 2012-07-24T11:38:40.367 に答える