繁体   English   中英

递归 function 作用于可变参数 class 模板参数

[英]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 旨在递归地从每个ComponentArraypop_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM