各种集合的模板类部分专用化
Template class partial specialization for kinds of collections
我正在尝试编写 2 个模板部分专用化,它们应该以不同的方式处理序列化序列容器和关联容器,但似乎根本没有使用序列容器专用化,因为编译器试图用错误的专用化来专门化它,这是代码:
template<typename W, typename T, template<typename...> class C, typename... Args>
class Archiver<W, C<T, Args...>>
{
public:
template<typename U = C<T, Args...>, typename std::enable_if<std::is_same<typename U::value_type, T>::value, int>::type = 0>
static void serialize(const W& w, const C<T, Args...>& container)
{
...
}
template<typename U = T, typename std::enable_if<!std::is_base_of<archive::require_placement_move, U>::value, int>::type = 0,
typename J = C<T,Args...>, typename std::enable_if<std::is_same<typename J::value_type, T>::value, int>::type = 0>
static void unserialize(const W& r, const Context& c, C<T,Args...>& container)
{
...
}
template<typename U = T, typename std::enable_if<std::is_base_of<archive::require_placement_move, U>::value, int>::type = 0,
typename J = C<T,Args...>, typename std::enable_if<std::is_same<typename J::value_type, T>::value, int>::type = 0>
static void unserialize(const W& r, const Context& c, C<T,Args...>& container)
{
...
}
};
template< typename W, typename K, typename T, template<typename...> class M, typename... Args>
class Archiver<W, M<K, T, Args...>>
{
public:
template<class U = M<K,T,Args...>, typename std::enable_if<std::is_same<typename U::key_type, K>::value && std::is_same<typename U::mapped_type, T>::value, int>::type = 0>
static void serialize(const W& w, const M<K,T,Args...>& container)
{
...
}
template<class U = M<K,T,Args...>, typename std::enable_if<std::is_same<typename U::key_type, K>::value && std::is_same<typename U::mapped_type, T>::value, int>::type = 0>
static void unserialize(const W& r, const Context& c, M<K,T,Args...>& container)
{
...
}
};
如果我尝试使用
Writer w;
Archiver<Writer, std::list<float>>::serialize(...);
该决议是在第二个专业化上完成的,因此导致
Candidate template ignored: substitution failure [with U = std::__1::list<float, std::__1::allocator<float> >]: no type named 'key_type' in 'std::__1::list<float, std::__1::allocator<float> >'
这应该意味着先验地排除了第一个特化,就像演绎分辨率选择与地图相关的解决方案一样。或者也许我错过了一些非常愚蠢的东西,因为我一直在处理这段代码。
我认为你对SFINAE的使用有点不对劲。
您将在Archive
模板中显式指定容器类型。一些未知的C++规则意味着当您通过std::list<float>
时选择第二个专业化。然后将 SFINAE 应用于 serialize
函数,消除唯一可用的重载(因此出现错误消息)。因为选择了Archive
的第二个专业化,所以甚至从未考虑过第一个专业化中的serialize
功能。这不是你想要的。
由于您明确指定了容器类型,因此我不确定您为什么要尝试使用 SFINAE。要正确地分别专门化序列和关联容器,您可能需要等到概念标准化。在那之前,你可以做一些幼稚的事情,比如根据类型别名key_type
的存在进行专业化(这是你已经在做的事情)。
下面是一个示例:
#include <type_traits>
template<typename>
using void_t = void;
template<typename T, typename = void>
struct has_key_type : std::false_type
{
};
template<typename T>
struct has_key_type<T, void_t<typename T::key_type>> : std::true_type
{
};
template<typename C, typename = std::enable_if_t<has_key_type<C>::value>>
void serialize(C const& c)
{
};
template<typename C, typename = std::enable_if_t<!has_key_type<C>::value>, typename = void>
void serialize(C const& c)
{
};
#include <iostream>
#include <list>
#include <map>
int main()
{
serialize(std::list<int>());
serialize(std::map<float, float>());
}
- 从非模板类调用专用模板方法
- '将成员函数仅添加到类的专用模板
- 具有不同非类型模板参数的模板类部分专用化
- 类模板专用化演绎是否应该考虑演绎指南参数初始化?
- 组合多个类模板专用化
- 如何将类成员专用于多个模板值(常量)?
- C++函子的类模板专用化
- C++类模板专用变量
- 一种安全、符合标准的方法,使类模板专用化仅在实例化时才无法使用"static_assert"进行编译
- 类模板专用化的前向声明
- 具有模板模板参数的类模板专用化
- 多种类型的类模板专用化
- 类模板专用化部分排序和函数合成
- 如何为非类型模板类的专用化定义声明之外的方法
- 类是否可以包含基类作为成员,该基类稍后专用于派生类
- 如何使用类模板专用化创建别名模板的专用化
- 嵌套类模板专用化问题
- 类模板专用化中的成员变量别名
- 只更改一个成员函数的类模板专用化
- 模板类与模板类的专用化