例如,我有一个基类A
及其子类B
,C
等等。 B
和C
也可以拥有其子类。该结构是一个具有根A
的树。树中的每个类都分配了一个不同的整数来标识自己。整数id的值和顺序没有限制。确保不同类别的不同。
我的问题是如何通过使用类似模板技术巧妙地(或自动地)执行此操作,因为手动分配容易出错。任何获得id的方法都很好,比如
class A
{
public:
static const id = ...;
};
或
template<class A>
struct Id
{
enum { value = ... };
};
答案 0 :(得分:1)
最简单的方法只是一个功能
int nextId() {
static int rval = 1;
return rval++;
}
class A { public: static const id = nextId(); };
class B { public: static const id = nextId(); };
class C { public: static const id = nextId(); };
只要您不需要在程序开始时使用动态初始化中的ID,这将有效。
编辑:如果这还不够,下一步就是对模板中的静态变量做同样的事情。这适用于编译单元,但仍然是动态初始化时间。
template <typename DummyT = void>
struct CommonCounter
{
public:
static int nextId() {
static int rval = 1;
return rval ++;
}
};
template <typename T>
struct IdFor
{
static int value()
{
static int rval = CommonCounter<>::nextId();
return rval;
}
};
class A { public: static const id = IdFor<A>::get(); };
答案 1 :(得分:1)
你可以这样做。这应该在同一个编译器上给出相同的顺序。您还可以修改关键字以获取已知订单并在初始化时检测问题。简单的实现,未经过测试。
#include <typeinfo>
class A {
public:
virtual ~A();
static void register_type(std::type_info const& t);
int id() const;
};
template<class T>
struct DoInitA
{
DoInitA() { A::register_type(typeid(T)); }
};
class B : public A
{
static DoInitA<B> s_a_init;
public:
~B() { }
};
//
// Implementation file.
//
#include <vector>
#include <functional>
namespace {
struct TypeinfoLess {
typedef std::reference_wrapper<const std::type_info> value_type;
bool operator()(value_type const& lhs, value_type const& rhs) const {
return lhs.get().before(rhs.get());
}
};
}
typedef std::vector<std::reference_wrapper<const std::type_info>> TypeVector;
static TypeVector s_types;
static bool s_init_complete = false;
A::~A() { }
void A::register_type(std::type_info const& t)
{
static int s_counter = 0;
if (s_init_complete)
throw std::runtime_error("Late initialisation");
s_types.push_back(std::reference_wrapper<const std::type_info>(t));
}
int A::id() const
{
if (!s_init_complete) {
sort(s_types.begin(), s_types.end(), TypeinfoLess());
s_init_complete = true;
}
for (size_t i = 0; i < s_types.size(); ++i)
if (s_types[i].get() == typeid(*this)) return i;
throw std::runtime_error("Uninitialised type");
}