Как расширить шаблон класса variadi c - PullRequest
2 голосов
/ 21 апреля 2020

Упрощенно Я пытаюсь сделать следующее:

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 Ответ

3 голосов
/ 21 апреля 2020

В c ++ 17 вы можете сделать это с выражением сгиба над оператором запятой

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

до c ++ 17 вы можете сделать что-то вроде

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

Обратите внимание на запятую в списке инициализаторов. Это происходит потому, что initObject возвращает void, и вы не можете иметь initializer_list из void s

Вот еще одно более общее решение. Это слишком сложно для этого случая, но может быть полезно.

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...>()();
    }
};
...