有关模板类专用化的范例
Paradigm regarding template class specialization
我目前正在编写一个模板类,用于将数据存档(或序列化(和取消存档为二进制格式/从二进制格式取消存档。首先,我试图关闭我将使用的模式。我主要倾向于使用模板,因为解压缩器没有用于方法重载的输入类型。例如,以下示例是可以的:
Archiver ar;
int i;
archive(ar, i);
但它的对应物不是:
Unarchiver unar;
int i;
i = unarchive(unar);
我想避免使用该函数的名称,例如unarchive_int
,因为使用模板时会很麻烦。说:
template <class T> class SomeClass
{
public:
void doSomething()
{
// Somewhere
T value = unarchive(unar);
}
};
这会让事情变得混乱,因此我宁愿为此真正使用模板,而之前的表达式会T value = unarchive<T>(ar);
.如果第一个或唯一的参数始终是存档器和非存档器对象,那么编写全局函数似乎也很愚蠢(可以说(;模板类似乎按顺序排列:
template <class T> class Archiver
{
public:
void archive(T obj);
};
这有效,但存档方法始终复制其输入对象。这对于 POD 数据类型是可以的,但对于哪些类来说就不行了。解决方案似乎很明显,而是使用 const 引用,如 void archive(const T & obj)
,但现在通过引用传递整数、浮点数和其他 POD 似乎也很愚蠢。虽然我会对这个解决方案感到满意,但我试图走得更远一点,让对象进行区分。我的第一个方法是std::enable_if
,同时默认假设一个副本(对于所有非类成员(并提供一个类专用化,其中 archive
方法通过引用获取其输入。它不起作用。代码如下:
template <class T, class E = void>
class Archiver
{
public:
// By default, obj is passed by copy
void archive(T obj);
};
template <class T>
class Archiver<T, typename std::enable_if<std::is_class<T>::value && !std::is_pod<T>::value>::value>
{
public:
// I would expect this to be used instead if is_class<T> && !is_pod<T>
void archive(const T & obj);
};
问题是第二个声明对编译器根本不可见,这里有证据:
template <> void Archiver<std::uint8_t>::archive(uint8_t obj);
template <> void Archiver<std::string>::archive(const std::string & obj);
前者编译良好,但后者给出:
"存档"的外联声明与 中的任何声明都不匹配
'Archiver<std::__1::basic_string<char>, void>'
另一方面,如果我通过复制获得std::string
,如果编译就可以了。我想我知道为什么会发生这种情况,编译器选择第一个模板,因为它对于两个声明都足够通用,但是我如何让它选择更专业的版本?
你想要std::enable_if<...>::type
,而不是std::enable_if<...>::value
。
这是一个完整的演示:
#include <type_traits>
#include <cstdint>
#include <string>
template <class T, class E = void>
struct Archiver {
void archive(T obj);
};
template <class T>
struct Archiver<T, typename std::enable_if<std::is_class<T>::value && !std::is_pod<T>::value>::type>
{
void archive(const T & obj);
};
template <> void Archiver<std::uint8_t>::archive(std::uint8_t obj);
template <> void Archiver<std::string>::archive(const std::string & obj);
IIUC,问题归结为如何定义针对调用函数进行优化的泛型模板类型。
为此,您可以考虑 boost::call_traits
,特别是param_type
:
template<typename T>
void foo(typename boost::call_traits<T>::param_type t);
- .cpp和.h文件中的模板专用化声明
- 调用专用模板时出错"no matching function for call to [...]"
- 模板专用化(按容器):value_type
- 静态数据成员模板专用化的实例化点在哪里
- 特征 3 类的模板专用化
- Visual Studio 2017 不允许我创建 C++ 专用模板
- 字符串化递归的"std::vector<std::vector<...>>"而不使用部分模板函数专用化
- 具有常量引用参数的函数模板专用化
- 使用其他模板的模板专用化
- 使用专用显卡进行 OpenGL 渲染时帧速率较低
- 嵌套模板显式专用化
- 如何检查模板专用化是否是基本模板的子类?
- C++:部分模板专用化用例
- 通过依赖类型使用非类型模板参数的单类型模板参数类模板的部分专用化
- 使用对象的基类部分模板专用化对对象进行哈希处理::哈希
- 在 C++20 中是否不再允许在 std 中对程序定义类型的函数模板进行专用化?
- 为什么依赖模板类型在部分专用化中不可推导?
- 如何为静态常量模板化专用整数值分配存储
- 模板类的部分模板专用化,如 std::function
- 有关模板类专用化的范例