比如我想实现一个这样的模板函数:
template<typename T>
int GetTypeIndex() {}
它总是为同一个“T”返回行列式从零开始的索引,最后是一个在编译时获取所有“T”总数的方法(constexpr 或宏?)
struct A
{
};
struct B
{
};
GetTypeIndex<A>();// returns 0,
GetTypeIndex<B>();// returns 1,
size_t sizeTable[ALL_TYPE_COUNT]; //ALL_TYPE_COUNT equals to 2 hence GetTypeIndex has 2 specialization(A and B)
我已经通过预先声明每个“T”并用一些宏包裹了
__COUNTER__
来做到这一点,但它只是不太方便,并且在其他地方使用__COUNTER__
会破坏整个设计。
我只是想摆脱那些宏观技巧。
编辑: 我的英语很差,所以我决定放上我之前用宏所做的内容来帮助理解我的意思。
#define INDEXED_TYPE_DEFINE_BEGIN \
template<typename T> int GetTypeIndex() = delete;
#define INDEXED_TYPE_DEFINE_END \
constexpr int INDEXED_TYPE_COUNT = __COUNTER__;
#define AS_INDEXED_TYPE(T) T\
constexpr int Index_##T= __COUNTER__;\
template<> inline int GetTypeIndex<T>() { return Index_##T; }
用户代码如下:
COMPONENT_DEFINE_BEGIN
typedef struct
{
float x;
float y;
}
AS_INDEXED_TYPE(Position)
typedef struct
{
float min;
float max;
}
AS_INDEXED_TYPE(Range)
COMPONENT_DEFINE_END
GetTypeIndex() 将返回 0 GetTypeIndex() 将返回 1 INDEXED_TYPE_COUNT 等于 2,我可以在编译时使用它
仅保留所有类型的单个列表可能会更容易:
#include <tuple>
#include <utility>
#include <type_traits>
#include <cstddef>
using all_types = std::tuple<
A, B, ...
>; // These don't need to be complete, i.e., just forward declarations work
// Depending on your C++ version, you can use something from https://stackoverflow.com/q/41579477 instead
template<typename T>
inline constexpr std::size_t type_index = []<std::size_t... I>(std::index_sequence<I...>){
std::size_t result = -1;
((std::is_same_v<T, std::tuple_element_t<I, all_types>> ? void(result = I) : void()), ...);
if (result == -1) throw "type_index<T>: T not in all_types";
return result;
}(std::make_index_sequence<std::tuple_size_v<all_types>>{});
template<std::size_t I>
using index_to_type = std::tuple_element_t<I, all_types>;
std::size_t sizeTable[std::tuple_size_v<all_types>];
static_assert(type_index<A> == 0);
static_assert(type_index<B> == 1);
https://godbolt.org/z/nr6v14Gaz
这不需要宏,但会强制您在一个地方声明所有类型(它们不能是零碎的),但听起来您已经在这样做了。