【发布时间】:2020-01-17 20:33:46
【问题描述】:
我正在制作一个实体组件系统库,利用模板元编程在编译时评估签名位集数据,并允许在不使用#define MAX_COMPONENTS some-number 的情况下获得精确的位集大小。
我正在使用 Boost Hana 并有一个看起来像这样的函数:
template <auto T>
static constexpr Bitset signatureBitset = Bitset(
hana::fold(SignatureList[hana::integral_c<std::size_t, signatureID<T>>], 0,
[](auto l, auto r) {
return l | 1 << inferProperty<primitiveBit>(r);
}));
它的作用是计算给定签名的 constexpr Bitset。签名是 ECS 组件和标签类型的 hana::tuple_t。
primitiveBit 返回模板参数类型组件/标签的位偏移量。由于hana::fold lambda 不提供当前r 的类型,我不能简单地调用primitiveBit<RType>(RType 未定义)。
最简单的可能解决方案是编写每个模板“函数”的副本,但作为实际的 constexpr 函数而不是静态 constexpr 对象,但我试图避免这种情况,因为编写了 30 多个重复函数,所有这些都可以
template <typename T>
static constexpr auto inferFunctionName(hana::basic_type<T> t) {
return functionName<T>;
}
看起来很笨,会让一切变得更难维护。上面的代码看起来也很简单,可以使用模板函数将模板 constexpr 对象作为模板参数抽象出来。
这是我目前拥有的:
template <template<typename> typename TReturn, typename T>
constexpr auto inferProperty(hana::basic_type<T> t) {
return TReturn<T>();
}
inferProperty<primitiveBit>(r) 抛出一个编译错误,说它与定义的模板签名不匹配。
由于 T 未在 lambda 中定义,因此不能使用 template <template<typename T> typename TReturn, typename T>。
【问题讨论】:
-
有什么原因
decltype(r)在 lambda 中不起作用? -
@JackC。类型被包裹在 hana::basic_type
中,所以 decltype(r) 是 hana::basic_type 。经过一番折腾, typename decltype(r)::type才是真正的解决方案。
标签: c++ templates lambda template-meta-programming boost-hana