为类型集合生成标识符

Generate identifiers for a collection of types

本文关键字:标识符 集合 类型      更新时间:2023-10-16

假设我有一个类型为A, B, C, ....的集合

这些类型只用于标签调度,所以我希望它们是空的/无状态的和最小的(空体):

struct A {};
struct B {};
struct C {};

然后我需要的是为每个类型创建唯一ID的方法。这个ID还必须是编译时常数。

我的第一次尝试是,非常典型地,有一个专门针对每种类型的结构,用static const成员保存ID的值:

template <typename T>
struct getID;
template <>
struct getID<A>
{
    static const int ID = 1;
};
template <>
struct getID<B>
{
    static const int ID = 2;
};
template <>
struct getID<C>
{
    static const int ID = 3;
};
template<typename T>
void testID(T val)
{
    cout << getID<T>::ID << endl;
}
int main()
{
    testID(A{});
    testID(B{});
    testID(C{});
    return 0;
}
  1. 有更简洁的实现吗?
  2. 我认为这是一个糟糕的设计,对于我添加到"集合"的每个新结构,代码的不同部分必须正确更新。是否有一种方式有/生成这个结构-> ID映射?

如果您不需要持久的id,您可以这样做:

class A {};
class B {};
class C {};
int getNextID()
{
   static int nextID = 0;
   return ++nextID;
}
template <typename T> struct GetID
{
   static int id()
   {
      static int id = getNextID();
      return id;
   }
};
int main()
{
   cout << GetID<A>::id() << endl;
   cout << GetID<B>::id() << endl;
   cout << GetID<C>::id() << endl;
   cout << GetID<int>::id() << endl;
   cout << GetID<C>::id() << endl;
};

运行上述程序的输出:

<>之前123.43.

创建types<Ts...>列表。typedef:按顺序列出类型的中心实例。使用该列表中的索引作为唯一id,它可以在编译时(或者在某些情况下,在运行时)客观地与类型关联。

作为一种替代方法,滥用__LINE__并在一个文件中使用所有宏。

template<class...>struct types{typedef types type;};
template<class T, class types>struct index_of_type;
template<class T, class... Ts>
struct index_of_type<T, types<T, Ts...>>:
  std::integral_constant< unsigned, 0 >
{};
template<class T, class T0, class... Ts>
struct index_of_type<T, types<T0, Ts...>>:
  std::integral_constant< unsigned, type_index<T, types<Ts...>>::value+1 >
{};
template<unsigned N, class types>struct type_at_index;
template<unsigned N, class T0, class... Ts>
struct type_at_index<N, types<T0, Ts...>>:type_at_index<N-1, types<Ts...>> {};
template<class T0, class... Ts>
struct type_at_index<0, types<T0, Ts...>> {
  typedef T0 type;
};
template<unsigned N, class types>
using type_at_index_t = typename type_at_index<N,types>::type;

如果我是对的,你可以使用这个:

#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
#define GET_ID ((int)(STRINGIFY(__FILE__)":"STRINGIFY(__LINE__)))

请注意,在同一文件的同一行上,该宏的两个实例可能产生相同的数字。