I want to replace this enum: enum{ eTagA, eTagB,...}
.
With instances of classes. This allows to append new tags, without modifying the enum.
I've got following code:
#include <memory>
#include <list>
struct TagBase {
bool operator== (const TagBase& other) const {
return typeid(*this) == typeid(other);
}
bool operator!= (const TagBase& other) const {
return !(*this == other);
}
virtual ~TagBase() = default;
};
bool operator== (const std::unique_ptr<TagBase>& lhs, const TagBase& base) {
return base == *(lhs.get());
}
class Namespace {
public:
template<typename T>
void AddTag() {
tags.push_back(std::unique_ptr<T>(new T()));
}
bool HasTag(const TagBase& tag) const {
return std::find(std::begin(tags), std::end(tags), tag) != tags.end();
}
private:
// using of std::unique_ptr is the only way?
std::list<std::unique_ptr<TagBase>> tags;
};
struct TagA: public TagBase {};
struct TagB: public TagBase {};
struct TagC: public TagBase {};
int main (int argc, const char* argv[])
{
Namespace nm;
nm.AddTag<TagA>();
nm.AddTag<TagB>();
assert(nm.HasTag(TagA{}));
assert(nm.HasTag(TagB{}));
assert(nm.HasTag(TagC{}) == false);
}
It works, but I have some thoughts about:
- Using "typeid" in this context is appropriate? Is this portable?
- I can't use raw TagBase class in "std:list" because of slicing. Can I avoid to use "unique_ptr" because of heap allocation?
- Maybe there is a better pattern to do this?
I also tried to do this with intense use of templates(std::is_same ... etc) but haven't got proper solution.
Aucun commentaire:
Enregistrer un commentaire