-1

In brief : how to create variadic tuple from given types's child?

In code below there is erroneous type children in get_children call. The goal is to receive tuple with Child derived from given elements.

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

Thanks in advance!

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • There's some serious [object orgy](https://en.wikipedia.org/wiki/Object_orgy) going on in your design... – JHBonarius Oct 30 '19 at 13:51
  • It's a theoretical issue. In reality Child will be another, non templated class. – Oleksandr N. Oct 30 '19 at 14:24
  • Note that the pack is `T`, not `T...`β€”the ellipsis is not part of its *name*, but is used to expand a type name or expression expressed in *terms* of it. – Davis Herring Oct 30 '19 at 20:46

2 Answers2

1

Because you tagged c++17, use 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>
}

Demo

rafix07
  • 20,001
  • 3
  • 20
  • 33
0

What about

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

?

I mean... the single type is T::Child so, to repeat the types, you have to place the ellipsis (...) after the type, so T::Child....

But, given a generic type T, T::Child could be a type but also a member or a method. So you need typename before to inform the compiler that the following T::Child is a type and not a member or other.

max66
  • 65,235
  • 10
  • 71
  • 111