通过 C++ 元编程在编译时自动为每个模板专门化分配索引?

问题描述 投票:0回答:1

比如我想实现一个这样的模板函数:

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,我可以在编译时使用它

c++ metaprogramming template-meta-programming
1个回答
0
投票

仅保留所有类型的单个列表可能会更容易:

#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

这不需要宏,但会强制您在一个地方声明所有类型(它们不能是零碎的),但听起来您已经在这样做了。

© www.soinside.com 2019 - 2024. All rights reserved.