[英]Call variadic function template with template parameters of variadic class template?
[英]Recursive function acting on variadic class template parameters
所以我有以下(减少)类:
template <typename A, typename... B>
struct ComponentTupleAccessor:
public ComponentArray<A>,
public ComponentTupleAccessor<B...>
{
ComponentTupleAccessor(const uint32_t capacity):
ComponentArray<A>(capacity),
ComponentTupleAccessor<B...>(capacity)
{}
};
template <typename A>
struct ComponentTupleAccessor<A>:
public ComponentArray<A>
{
ComponentTupleAccessor<A>(const uint32_t capacity):
ComponentArray<A>(capacity)
{}
};
template <typename A, typename ...B>
class ComponentTuple {
ComponentTupleAccessor<A, B...> m_Components;
uint32_t m_Capacity;
public:
ComponentTuple(const RB32u capacity):
m_Capacity{capacity},
m_Components(capacity)
{}
template <typename S, typename ...T>
void pop_back() {
m_Components.Component<S>::pop_back();
pop_back<T...>();
}
template <typename S>
void pop_back() {
m_Components.Component<S>::pop_back();
}
void pop_back() {
pop_back<A, B...>();
}
};
ComponentArray
class 基本上是一个包含一组特定类型组件的向量的包装器。
ComponentBlockTupleAccessor
class 或多或少模拟了 std::tuple 的缩减版本,其中任意数量的唯一类型的ComponentArray
可以使用可变参数模板继承到 class ComponentTuple
中。
ComponentTuple
中的pop_back
function 旨在递归地从每个ComponentArray
中pop_back
一个元素。
在ComponentTuple
class 之外,我希望能够简单地调用类似compTupleInstance.pop_back()
的东西,并且所有ComponentArray
都应该删除它们的最后一个元素。
我得到一个编译错误“重载'pop_back()'的调用不明确”pop_back();
我似乎无法弄清楚 A、B(包)、S 和 T(包)模板参数的组合,它可以为我提供所需的功能。 我在这里想念什么?
编辑:这是一个简单的使用场景:
// ComponentTuple contains an int and a float ComponentArray with capacity 8.
ComponentTuple<int, float> dut(8);
// Push a set of new components to the ComponentArrays.
// This function has a similar structure to that of pop_back.
dut.push_back({8}, {3.141f});
// Another one
dut.push_back({4}, {2.718f});
// Remove the last element from all of the ComponentArrays.
dut.pop_back();
ComponentTuple 模板参数将始终是唯一类型,并且始终大于一。
问题的副本:
template <typename S, typename ...T> // T can be empty
void pop_back() {
m_Components.Component<S>::pop_back();
pop_back<T...>();
}
template <typename S>
void pop_back() {
m_Components.Component<S>::pop_back();
}
如果我调用pop_back<A>()
我有S = A
。 但是,我是用T
为空调用第一个方法,还是调用第二个方法?
核心问题: template <typename S, typename... T>
和template <typename S>
当只有一个模板参数(包可以为空)时,对于编译器来说看起来同样好。 它无法决定使用哪个重载。
解决方法:可以使用 fold 表达式(c++17 或以上)。
void pop_back() {
(m_Components.ComponentArray<A>::pop_back(), ... , m_Components.ComponentArray<B>::pop_back());
}
...如果像这样使用代码也会中断(即使使用上面的折叠表达式): ComponentTuple<int, int, double>
(不明确的基类)。
感谢您的帮助, <typename S>
和<typename S, typename... T>
之间的歧义现在看起来很明显,因为您已经指出了这一点。 出于这个原因,似乎不可能按照我尝试的方式去做。
我最终使用if constexpr
来测试递归是否是最后一个类型,因此我可以在该点终止递归。 我更喜欢这一点,因为在非模板化pop_back
中,没有提供未用于声明 class 的模板参数的风险。 例如
ComponentTuple<int, float> dut(8);
push_back<Banana, char>; // Not int, float so should cause compile error.
使用constexpr
方法,我可以将pop_back
function 私有化(参见下面的pop_back_
),并且只公开无参数版本,以便只能以正确的方式调用该方法:
template <typename A, typename ...B>
class ComponentTuple {
ComponentTupleAccessor<A, B...> m_Components;
uint32_t m_Capacity;
template <typename S, typename... T>
void pop_back_() {
m_Components.ComponentBlock<S>::pop_back();
if constexpr (sizeof...(T) > 0) {
pop_back_<T...>();
}
}
public:
ComponentTuple(const RB32u capacity):
m_Capacity{capacity},
m_Components(capacity)
{}
void pop_back() {
pop_back_<A, B...>();
}
};
显然我需要确保我至少使用 c++17 来使用if constexpr
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.