如何为模板化类型提供 void* 访问器?
How to provide a void* accessor for a templated type?
我有一个模板化的自定义容器类:
template<typename T>
class MyContainer {
T Get();
void Put(T data);
};
我想将指向此容器的指针传递给一个函数,该函数将作为通用数据访问容器的数据 - 即char*
或void*
.想想序列化。这个函数有点复杂,所以由于模板的原因,最好不要在标题中指定它。
// Errors of course, no template argument
void DoSomething(MyContainer *container);
我可以要求用户提供 lambda 或子类或执行转换的东西。但我似乎想不出一个干净的方法来做到这一点。
我考虑过通过MyContainer
保存一些具有virtual void Serialize(void *dest) = 0;
函数的抽象MyData
类的容器来完全避免模板。用户将MyData
子类以提供其类型和序列化,但这似乎变得非常复杂。效率也很低,因为它需要存储指向MyData
的指针以避免对象切片,并且MyData
通常非常小,并且容器将容纳大量(大量指针存储和取消引用)。
你不需要任何char*
、void*
或继承。
请考虑以下简化的实现:
template <class T>
void Serialize (std::ostream& os, const MyContainer<T>& ct) {
os << ct.Get();
}
突然间,这适用于具有合适operator<<
过载的任何T
。
没有合适的operator<<
重载的用户类型怎么办?只需告诉用户提供一个。
当然,您可以使用任何重载函数。它不必命名为operator<<
.您只需要将其名称和签名传达给用户并要求他们重载即可。
您可以使用纯虚函数为容器引入非模板基类,该函数返回指向原始数据的指针并在容器中实现它:
class IDataHolder
{
public:
virtual ~IDataHolder(); // or you can make destructor protected to forbid deleteing by pointer to base class
virtual const unsigned char* GetData() const = 0;
};
template<typename T>
class MyContainer : public IDataHolder
{
public:
T Get();
void Put(T data);
const unsigned char* GetData() const override { /* cast here internal data to pointer to byte */}
};
void Serialize(IDataHolder& container)
{
const auto* data = container.GetData();
// do the serialization
}
将指向此容器的指针传递给一个函数,该函数将作为通用数据访问容器的数据 - 即
char*
或void*
.想想序列化。
一般做不到,因为你对T
一无所知.通常,类型不能通过char *
或类似方式作为原始 blob 进行处理(例如复制、访问等)。
因此,您需要限制T
可以是什么,最好是强制执行它,否则永远不要将其用于会触发未定义行为的T
。例如,您可能希望断言std::is_trivially_copyable_v<T>
成立。尽管如此,在处理此类数据时,您仍然必须考虑其他可能的问题,例如字节序和打包。
这个函数有点复杂,所以由于模板的原因,最好不要在标题中指定它。
不知道你这是什么意思。编译器可以非常轻松地处理标头,特别是大量的模板代码。只要你没有达到一些 Boost 库的水平,你的编译时间就不会爆炸。
我考虑过通过
MyContainer
保存一些具有virtual void Serialize(void *dest) = 0;
函数的抽象MyData
类的容器来完全避免模板。用户将MyData
子类以提供他们的类型和序列化,但这似乎变得非常复杂。效率也很低,因为它需要存储指向MyData
的指针以避免对象切片,并且MyData
通常非常小,并且容器将容纳大量(大量指针存储和取消引用)。
一般来说,如果你想要一个模板,做一个模板。为此使用动态调度可能会降低性能,特别是当您必须对即使是简单的类型进行调度时。
最后一点,我建议看看一些可用的序列化库,看看他们是如何实现的,不仅在性能方面,而且在易用性、与现有代码的集成等方面。例如,Boost Serialization和Google Protocol Buffers。
- 通过方法访问结构
- 为什么全局函数 void showA(A&x) 能够访问 A 类的私有成员?
- 如何在 C++ 中从 void 返回函数访问变量
- 在 c++ 中访问嵌套字典unordered_map<字符串、void*>?
- 访问由 void 指针引用的结构的成员
- 如何为模板化类型提供 void* 访问器?
- 从 void 函数访问局部变量
- 如何转换 void* 以访问结构的静态数据成员?
- 在 void getData() 中,如何访问由 void* 指针重新调整的内存位置
- 如何打印 /访问const void指针的内容
- 访问void函数中的变量以用于其他函数?C++
- 访问 C 中保存C++对象的 void 指针的内容
- 访问对象 void 指针 c++ 的成员
- 在 void 方法 (c++) 中访问数组
- 如何从 void 指针将属性访问到结构中
- 在构造函数中强制转换void*并访问值
- 如何在c++中使用void指针(泛型)访问类成员
- 无法从 void 函数访问 Qt UI
- c++访问void*中的特定地址
- 将中等数量的T*静态强制转换为void*时发生访问冲突