如何扩展可变参数模板类

时间:2020-04-21 12:49:33

标签: c++ c++11 c++14

简化,我正在尝试以下操作:

template<typename T>
struct SomeObject
{
    T value;
};

template<typename... Ts>
struct Container : public SomeObject<Ts>...
{
    void init()
    {
        (initObject<Ts>())...; // not working: how to execute initObject for each type
    }

    template<typename T>
    void initObject()
    {
        SomeObject<T>::value = new T();
        // do some other stuff
    }
};

class A {};
class B {};

int main()
{
    auto c = new Container<A, B>();
    c->init();
}

在我的用例中,我无法在构造函数中进行初始化。那么如何获得init方法以针对所有类型正确展开?

1 个答案:

答案 0 :(得分:3)

在c ++ 17中,您可以使用fold expression通过逗号运算符来实现

(initObject<Ts>(), ...);

在c ++ 17之前,您可以做类似的事情

std::initializer_list<int>{(initObject<Ts>(), 0)...};

请注意初始化列表中的逗号表达式。之所以在这里是因为initObject返回void,并且您不能有initializer_listvoid

这是另一个更通用的解决方案。在这种情况下,它太复杂了,但可能很有用。

template<typename... Ts>
struct Container : public SomeObject<Ts>...
{
    void init()
    {
        initObjects<Ts...>(); // not working: how to execute initObject for each type
    }

    template <typename ...Args>
    struct object_initializer;

    template <typename First, typename ...Rest>
    struct object_initializer<First, Rest...> {
        void operator ()() {
            SomeObject<First> obj{First()};
            object_initializer<Rest...>()();
        }
    };

    template <typename First>
    struct object_initializer<First> {
        void operator ()() {
            SomeObject<First> obj{First()};
        }
    };

    template<typename ...Args>
    void initObjects() {
        object_initializer<Args...>()();
    }
};