[英]C++ creating template specialisation in a typelist
I have the following struct: 我有以下结构:
template<typename tag_type>
struct tag{
typedef tag_type type;
enum { value = -1 }
};
I use this class as a typeid to identify specific classes at runtime. 我使用此类作为typeid来在运行时标识特定的类。 Each of these classes needs to be listed in a typelist and each tag specialization needs to have a different value. 这些类中的每一个都需要列在类型列表中,并且每个标记特化需要具有不同的值。
Is there a way to make the value
equal the index of the specialization in the list. 有没有办法使value
等于列表中的特化指数。
My goal is to make the maintenance of a list of specialized tag
with unique values as easy as possible... (I need to make sure each type in the list has a unique value or part of the system will crash) 我的目标是尽可能简单地维护具有唯一值的专用tag
列表...(我需要确保列表中的每个类型都具有唯一值或系统的一部分将崩溃)
EDIT: I failed to mention I use the values at compile time... 编辑:我没有提到我在编译时使用值...
A non C++11 implementation of what I think you mean, though you do not really specify the structure of the typelist. 我认为你的意思的非C ++ 11实现,虽然你没有真正指定类型列表的结构。
template <typename H, typename T>
struct typelist {
typedef H head;
typedef T tail;
};
template <typename T, typename List, int N>
struct typelist_index_i
{
typedef typename List::tail tail;
enum {
value = N + typelist_index_i<T, tail, N + 1>::value
};
};
template <typename List, int N>
struct typelist_index_i<typename List::tail, List, N>
{
enum {
value = N + 1
};
};
template <typename List, int N>
struct typelist_index_i<typename List::head, List, N>
{
enum {
value = N
};
};
template <typename T, typename List>
struct typelist_index
{
enum {
value = typelist_index_i<T, List, 0>::value
};
};
class A {};
class B {};
class C {};
typedef typelist<A, typelist<B, C> > the_types;
template<typename tag_type>
struct tag{
typedef tag_type type;
enum { value = typelist_index<tag_type, the_types>::value };
};
int main()
{
std::cout << tag<A>::value << std::endl; // 0
std::cout << tag<B>::value << std::endl; // 1
std::cout << tag<C>::value << std::endl; // 2
system("pause");
return 0;
}
If you don't mind the values not being available until runtime, you could utilize constructors being called for global objects to register the classes for you. 如果您不介意在运行时之前不可用的值,则可以使用为全局对象调用的构造函数来为您注册类。 Perhaps something like this: 也许是这样的:
template<typename tag_type>
struct tag {
typedef tag_type type;
int value;
// other info can go here, like a string representation of the class name
tag(void) {
register_class(this);
}
};
#define ADD_CLASS(tag_type) tag<tag_type> __g_tag_ ## tag_type
extern int __g_class_counter;
template<typename tag_type>
static inline void register_class(tag<tag_type> *ptag) {
ptag->value = __g_class_counter++;
// TODO: anything else
}
// in some CPP file
int __g_class_counter = 0;
You can then just use the macro ADD_CLASS
whenever you need to add a class to the list (you might need to move __g_class_counter
elsewhere and make an extern
declaration of it). 然后,只要需要在列表中添加类,就可以使用宏ADD_CLASS
(您可能需要在其他地方移动__g_class_counter
并对其进行extern
声明)。
Is this doing what you want? 这样做你想要的吗? It is using C++11 features, ie variadic templates. 它使用C ++ 11功能,即可变参数模板。 The index_of
struct returns the index of a type within a type list or -1 if the type list does not contain the given type. index_of
结构返回类型列表中类型的索引,如果类型列表不包含给定类型,则返回-1。 It is a helper struct that is used from within the type_list class. 它是一个在type_list类中使用的辅助结构。 The type_list class gets a list of classes and provides the sub-class template tag
, which provides access to the indices of individual types within the list by using the index_of
class template. type_list类获取类列表并提供子类模板tag
,该tag
使用index_of
类模板提供对列表中各个类型的索引的访问。
template <int, class...>
struct index_of;
template <int n, class type, class first, class ... types>
struct index_of<n, type, first, types...>
{
static constexpr int value = index_of<n+1, type, types...>::value;
};
template <int n, class type, class ... types>
struct index_of<n, type, type, types...>
{
static constexpr int value = n;
};
template <int n, class type>
struct index_of<n, type>
{
static constexpr int value = -1;
};
template <class ... types>
struct type_list
{
template <class type>
struct tag
{
static constexpr int value = index_of<0, type, types...>::value;
};
};
Usage: 用法:
using my_list = type_list<int, float, double>;
std::cout << "Tag of int: " << my_list::tag<int>::value << std::endl;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.