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_typeisstd::pair(const K, V)和 not std::pair(K, V)

所以,我想创建read(InsertIter)一个自动选择适当的方法readContainer(InsertIter)or 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 回答