Как сгенерировать кортеж для вариационных шаблонов детей? - PullRequest
0 голосов
/ 30 октября 2019

Вкратце: как создать переменный кортеж из дочерних типов данных?

В приведенном ниже коде в вызове get_children есть дочерние объекты ошибочного типа. Цель состоит в том, чтобы получить кортеж с Child, полученный из заданных элементов.

template<typename T>
class Elem{
public:
    T e;
    class Child{ public: T c; };

    Child child() { return Child{ .c = e}; };
};

template <typename... T>
class Collection{
public:
    using arr = std::tuple<T...>;
    arr elems;

    using children = std::tuple<T...::Child>;  /// **** HERE IS ERROR ***

    auto get_children(){
        children res;

        get_child<sizeof...(T)-1>( res );
        return res;
    }

private:
    template< size_t Num >
    auto get_child( children &res ){
        std::get<Num>(res) = std::get<Num>(elems).child();
        get_child<Num-1>(res);
    }

    template<>
    auto get_child<0>( children &res ){
        std::get<0>(res) = std::get<0>(elems).child();
    }
};

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 30 октября 2019

Поскольку вы пометили c ++ 17, используйте apply:

#include <iostream>
#include <tuple>
#include <boost/type_index.hpp>

template<typename T>
class Elem{
public:
    T e;
    class Child{ public: T c; };

    Child child() { return Child{ .c = e}; };
};

template <typename... T>
class Collection{
public:

    using arr = std::tuple<T...>;
    arr elems;

    auto get_children(){
        return std::apply( [](auto&&... e){ return std::make_tuple(  e.child()... ); } , elems);
    }

private:
};

int main()
{
    Collection<Elem<int>,Elem<char>,Elem<float>> c;
    auto t = c.get_children();
    std::cout << boost::typeindex::type_id_with_cvr<decltype(t)>().pretty_name() << std::endl;
     // std::tuple<Elem<int>::Child, Elem<char>::Child, Elem<float>::Child>
}

Демо

0 голосов
/ 30 октября 2019

Как насчет

using children = std::tuple<typename T::Child...>;

?

Я имею в виду ... единственный тип - T::Child, поэтому для повторения типов необходимо поместить многоточие (...) после типа, поэтому T::Child....

Но, учитывая универсальный тип T, T::Child может быть типом, а также членом или методом. Поэтому вам нужно typename, прежде чем сообщить компилятору, что следующий T::Child является типом, а не членом или другим.

...