我有一组C ++类,每个类必须声明一个唯一的顺序id作为编译时常量。
为此,我使用__COUNTER__
内置宏转换为一个整数,该整数在每次出现时都会递增。 ids不需要遵循严格的命令。唯一的要求是它们是顺序的并从0开始:
class A {
public:
enum { id = __COUNTER__ };
};
class B {
public:
enum { id = __COUNTER__ };
};
// etcetera ...
我的问题是:有没有办法使用C ++构造实现相同的结果,例如模板?
答案 0 :(得分:4)
以下是使用__LINE__
宏和模板执行此操作的可能方法:
template <int>
struct Inc
{
enum { value = 0 };
};
template <int index>
struct Id
{
enum { value = Id<index - 1>::value + Inc<index - 1>::value };
};
template <>
struct Id<0>
{
enum { value = 0 };
};
#define CLASS_DECLARATION(Class) \
template <> \
struct Inc<__LINE__> \
{ \
enum { value = 1 }; \
}; \
\
struct Class \
{ \
enum { id = Id<__LINE__>::value }; \
private:
使用示例:
CLASS_DECLARATION(A)
// ...
};
CLASS_DECLARATION(B)
// ...
};
CLASS_DECLARATION(C)
// ...
};
请参阅live example。
答案 1 :(得分:3)
明确的链接是否可以接受?
class A {
public:
static const unsigned int id = 1;
};
class B {
public:
static const unsigned int id = A::id+1;
};
这种方法的优点是你总能获得相同的Id,无论你的编译器是什么,你都知道它是什么。虽然采用__LINE__
或__COUNTER__
方法可能无法预测。缺点是,通过链接你的班级必须始终知道链上的前一个。
使用模板(和C ++ 11):
template <typename... T>
class Identificable;
template <>
class Identificable<> {
public:
static const unsigned int id = 1;
};
template <typename Prev>
class Identificable<Prev> {
public:
static const unsigned int id = Prev::id+1;
};
class A : public Identificable<> {
public:
};
class B : public Identificable<A> {
public:
};
答案 2 :(得分:2)
标准C ++具有 __LINE__
宏。
也就是说,__LINE__
是一个“C ++构造”,根据要求,与__COUNTER__
形成鲜明对比,而不是。{/ p>
__LINE__
与Visual C ++的__COUNTER__
的不同之处在于,当使用某个编译选项时,至少早期版本的Visual C ++会产生__LINE__
的乱码扩展。
根据您的需求,您可以简单地使用type_info
个实例进行身份识别。 C ++ 11增加了对比较type_info
的一般支持,称为 std::typeindex
。这意味着您可以使用标准集合。
答案 3 :(得分:1)
有没有办法使用C ++构造实现相同的结果,例如 作为模板?
是的,有:-)基本思想是使用链接分配的ID,这避免了使用__COUNTER__
,__LINE__
或之前提出的其他方法,并且不需要注入&#34;额外&#34;信息到类型定义。
以下是使用模板元编程在v1中为在C ++ 03上实现的计数器提出的解决方案的简要说明。两个模板特化ID_by_T
和T_by_ID
用于在编译时定义链接type <=> ID
。类型的ID是枚举常量。如果未定义链接,ID_by_T<type>::ID
将返回-1
,T_by_ID<undefinedID>::type
将返回null_t
预定义类型。宏DEF_TYPE_ID(type_name)
会在定义ID
链接时生成新的type <=> ID
。
此方法基于宏重定义:当使用#undef
未定义宏时,其值将扩展为C ++代码。例如:
DEF_TYPE_ID(int)
#undef PREV_TYPE
#define PREV_TYPE int
宏DEF_TYPE_ID
使用以下调用宏PREV_TYPE
的先前定义:ID_T_pair<type_name, ID_by_T<PREV_TYPE>::ID+1>
。这就是为什么我说关于链接分配的ID。