为许多类型创建"custom typeid"并缓存其 sizeof()
Create "custom typeid" for many types AND cache their sizeof()
E0,E1,...
有多种类型的元素,它们都来源于Element
。
class Element{ public: int id=0; } //"Element" can be edited
class E0: public Element{ ... }
class E1: public Element{ ... }
...
class E999: public Element{ ... }
如何为E0,E1,...
缓存sizeof()
?
它必须稍后通过"custom typeid"[#1]返回正确的值[#2]。
class CCollection{
template<class EX> EX* create(){ //(Edit)
//all EX* is created by this function
}
/** user only pass EX*, never pass Element* */ (Edit)
int toId(Element* element){//[#1] should replaced by template?
//....... return id, e.g. 0 for E0, 1 for E2, 2 for E1, ...
// can be in any order, but must unique and packed ........
}
int sizeOf(int id){//[#2]
//....... return size of EX
// must consistent with toId() ,
// e.g. sizeof(E0) for 0, sizeof(E2) for 1, sizeof(E1) for 2 ........
}
//....... other fields / functions, if necessary ............
}
如何实现?
要求:
- 不允许手动分配id-integer的
E0,E1,E2,...
,因为低维护性。 - 用户无需手动"注册"
E0,E1,E2,...
到CCollection
。
对于新类型的元素,例如E1000,不需要做任何修改。
…也就是说,CCollection
应该在E1000上"刚好工作"。 - 最高性能,例如:-
- 虚拟通话应该避免,除非完全不可避免。
使用 - 函数内部的静态变量是不好的
- 不要修改
E0,E1,E2,...
的代码
constexpr
设计的灵活性
- 如果
CCollection
的函数从未被某个E-X
调用,E-X
的管理可以省略(由您决定)。 - 只有一个CCollection实例
clue1: Template似乎是最有前途的路径,但我不确定。
clue2:(编辑)我计划的这段代码可能会有所帮助:-
template<class EX> int toId(EX* element){//[#1]
// register something?
}
你可以猜到,真正的问题远比这更大,
但这是我整个拼图中唯一缺失的一块拼图。
虽然我希望有代码,但只是一个指南真的很感激。
我认为以下这些并不会违反你的规则:
struct CCollection
{
template <typename T>
std::size_t toId() {
auto it = info.find(typeid(T));
if (it == info.end()) {
it = info.insert({typeid(T), {count++, sizeof(T)}}).first;
}
return it->second.id;
}
std::size_t sizeOf(const Base& base) const {
const auto& data = info.at(typeid(base));
return data.size;
}
std::size_t count = 0;
std::unordered_map<std::type_index, Data> info;
};
演示如果您可以在Element
和每个EX
之间添加一个中间类,那么这里是一个可能的解决方案(使用最小的工作示例):
#include<cstddef>
#include<memory>
#include<vector>
#include<cassert>
struct Element {
static std::size_t counter;
};
std::size_t Element::counter = 0;
template<typename>
struct ElementType: Element {
static const int type;
};
template<typename T>
const int ElementType<T>::type = Element::counter++;
struct E0: ElementType<E0> {};
struct E1: ElementType<E1> { int i; };
struct E2: ElementType<E2> {};
class CCollection {
void ensure(std::size_t type) {
if(!(type < sizes.size())) {
sizes.resize(type+1, 0);
}
}
template<typename EX>
void ensure() {
ensure(EX::type);
sizes[EX::type] = sizeof(EX);
}
public:
template<class EX>
std::shared_ptr<EX> create() {
ensure<EX>();
return std::make_shared<EX>();
}
template<typename EX>
std::size_t toId() {
ensure<EX>();
return EX::type;
}
std::size_t sizeOf(std::size_t type) {
ensure(type);
return sizes[type];
}
private:
std::vector<std::size_t> sizes;
};
int main() {
CCollection coll;
assert(coll.toId<E0>() != coll.toId<E1>());
assert(coll.toId<E0>() != coll.toId<E2>());
assert(coll.toId<E1>() != coll.toId<E2>());
assert(coll.sizeOf(0) == sizeof(E0));
assert(coll.sizeOf(1) == sizeof(E1));
assert(coll.sizeOf(2) == sizeof(E2));
assert(coll.sizeOf(0) != coll.sizeOf(1));
// ...
}
如果试图在不使用create
的情况下创建EX
的实例,则会出现示例代码中的问题。
总之:
- 你说不应该发生的。
- 你可以强制使用这个函数
-
CCollection
类被设计成如果你这样做,它会从sizeOf
返回0。
也就是说,它至少可以作为更详细的生产代码的基础。
相关文章:
- cmake更新缓存的变量
- 试图对缓存进行跨步测试,但程序并没有结束
- 缓存std::数组的选定元素,并在c++中自动保持其一致性
- 通过ccmake在cmake中缓存依赖选项
- 如何使我的 sizeof sum 结构与空参数包一起工作
- 同一对象的"sizeof"的不同答案
- 使用宏扩展的泛型:为什么指令缓存使用不当?
- 如何使缓存线程安全
- 为什么数组大小信息可用于"sizeof"运算符和 delete[] 运算符,但在将数组作为参数传递到
- 为什么 sizeof 在 C++ 中给出不正确的字节数?
- 存储指令是否会阻止缓存未命中的后续指令?
- sizeof(size_t) 可以小于 sizeof(int) 吗?
- 缓存局部性与函数调用
- Qt 网页程序集缓存
- 字符串数组上的 sizeof 运算符以 C++ 为单位给出不同的输出
- 为什么 sizeof(ar)/ sizeof(ar[0]) 在传递给函数时无法在向量上正常工作?
- 多线程减慢程序速度:无错误共享,无互斥锁,无缓存未命中,无小工作量
- std::shared_ptr vs std::make_shared:意外的缓存未命中和分支预测
- 多个 rocksdb 实例:使用单个共享缓存还是多个独立缓存?
- 为许多类型创建"custom typeid"并缓存其 sizeof()