创建“自定义类型ID";对于许多类型并缓存其sizeof() [英] Create "custom typeid" for many types AND cache their sizeof()
问题描述
元素E0,E1,...
的类型很多,都是从Element
派生的.
There are many type of elements E0,E1,...
, all of them derived from 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()
?
以后必须通过自定义typeid" [#1]返回正确的值[#2].
How to cache sizeof()
for E0,E1,...
?
It has to return the correct value [#2] later by "custom typeid" [#1].
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 ............
}
如何实现呢?
- 由于可维护性较低,不允许手动分配
E0,E1,E2,...
的id整数. - 用户不必手动将"
E0,E1,E2,...
"注册到CCollection
.
如果是新类型的元素,例如E1000,无需进行任何修改.
.....即CCollection
对于E1000应该是正常工作". - 最高性能,例如:-
- 应避免虚拟调用,除非完全不可避免.
- 如有可能,请使用
constexpr
. - 函数内部的静态变量不好.
- Manually assign id-integer of
E0,E1,E2,...
is not allowed, because of low maintainability. - User doesn't have to "register"
E0,E1,E2,...
toCCollection
manually.
When new type of Element, e.g. E1000, no modification have to be done.
..... i.e.CCollection
should be "just work" for E1000. - Highest performance, e.g. :-
- Virtual calling should be avoided, except totally unavoidable.
- Use
constexpr
if possible. - Static variable inside a function is not good.
设计的灵活性
- 如果某个特定的
E-X
从未调用过CCollection
的函数,则
E-X
的管理可以省略(由您决定). - 只有1个CCollection实例.
- If
CCollection
's functions are never called for a certainE-X
,
the management forE-X
can be omitted (up to you). - There is only 1 CCollection instance.
线索1:模板似乎是最有前途的途径,但我不确定.
clue1: Template seems to be the most promising path, but I am not sure.
线索2:(编辑)我计划的这段代码可能会有所帮助:-
clue2: (Edit) This snippet I have planed may help :-
template<class EX> int toId(EX* element){//[#1]
// register something?
}
您可以猜到,真正的问题远不止于此,
但这是我整个难题中唯一缺失的拼图.
As you can guess, the real problem is far bigger than this,
but this is the only one missing jigsaw of my whole puzzle.
尽管我希望获得代码,但真的很感谢指南.
Although I wish for code, just a guide is really appreciated.
推荐答案
如果您可以在Element
和每个EX
之间添加一个中间类,这是一个可行的解决方案(带有一个最小的有效示例):>
If you can add an intermediate class between Element
and each EX
, here is a possible solution (with a minimal, working example):
#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
的实例,则会出现示例代码中的问题.
无论如何:
The problem in the code in the example arises if one tries to create instances of EX
without using create
.
Anyway:
- 您说过它永远不会发生.
- 您可以强制使用该功能.
-
CCollection
类的设计目的是,如果您这样做,它将从sizeOf
返回0.
- You said it should never happen.
- You can enforce the use of that function.
- The
CCollection
class is designed so as it returns 0 fromsizeOf
if you do that.
也就是说,它至少可以作为更详细的生产代码的基础.
That said, it can serve as a base for a more elaborated production code at least.
这篇关于创建“自定义类型ID";对于许多类型并缓存其sizeof()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!