具有递归和 std::enable_if 的模板特化

问题描述

假设我想用下面的方式序列化下面的数据。有些数据是可通过内存复制序列化的,有些则不是。

    MemcpySerializable ser;
    NonMemcpySerializable nonser;

    const std::vector<MemcpySerializable> vec1;
    const std::vector<NonMemcpySerializable> vec2;

    FastBinarySerializer<MemcpySerializable>::SerializeValue(ser);
    FastBinarySerializer<NonMemcpySerializable>::SerializeValue(nonser);
      
    FastBinarySerializer<std::vector<MemcpySerializable>>::SerializeValue(vec1);
    FastBinarySerializer<std::vector<NonMemcpySerializable>>::SerializeValue(vec2);

前面提到的类型是这样定义的:

template<typename T>
struct IsMemcopySerializable
{
    static constexpr bool value = std::is_trivially_copyable<T>::value && std::is_trivially_destructible<T>::value &&
        !std::is_pointer<T>::value;
};

struct MemcpySerializable
{
};

template<>
struct IsMemcopySerializable<MemcpySerializable>
{
    static constexpr bool value = true;
};


struct NonMemcpySerializable
{
};

template<>
struct IsMemcopySerializable<NonMemcpySerializable>
{
    static constexpr bool value = false;
};

如您所见,两种结构体类型的唯一区别是 IsMemcopySerializable::value 中的值。

注意 IsMemcopySerializablestd::vector::value 对于所有 T 都是假的。

我们通过以下方式定义 FastBinarySerializer :

//Default Template Arguments
struct DefaultType;
struct NonDefaultType; //This is unused,but it may be helpful as a default template argument.

//Primary Template
template<typename T,typename U = DefaultType,typename Enable = void >
struct FastBinarySerializer;

template<typename T,typename U>
struct FastBinarySerializer<
    T,U,typename std::enable_if<
    IsMemcopySerializable<T>::value>::type>
{
    static void SerializeValue(const T& value) noexcept
    {
        //Memcopy serialization
    }
};

template<typename T,typename std::enable_if<
    !IsMemcopySerializable<T>::value>::type>
{
    static void SerializeValue(const T& value)
    {
        //Fallback case. This will only work for specific types (not std::vector<T>). 
        // We will assume that any nonspecialized type T with !IsMemcopySerializable<T>::value
        // will be handled by this function.
    }

};

template<typename T>
struct FastBinarySerializer<std::vector<T>,DefaultType,void>
{
    static void SerializeValue(const std::vector<T>& value)
    {
        FastBinarySerializer<uint32_t>::SerializeValue(value.size());

        for (auto& item : value)
        {
            FastBinarySerializer<T>::SerializeValue(item);
        }
    }
};

问题是以下行产生了这个错误

    FastBinarySerializer<std::vector<MemcpySerializable>>::SerializeValue(vec1);
      //error C2752: 'FastBinarySerializer<std::vector<MemcpySerializable,//std::allocator<MemcpySerializable>>,void>': more than one partial specialization 
      //matches the template argument list

问题在于 std::vector 不是 MemcopySerializable。 FastBinarySerializer 类模板匹配两个专业化。 有没有办法让 FastBinarySerializerstd::vector 仅与 std::vector 特化匹配? 我尝试使用 DefaultType 和 NonDefaultType 来强制优先使用 std::vector 特化无济于事。

我的限制: FastBinarySerializer 必须保留为类模板而不是函数模板。 SerializeValue 必须始终具有相同的函数签名。 我无法在类模板实例化中手动指定 DefaultType 或 NonDefault 类型。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)