【问题标题】:How to generate tuple for variadic templates children?如何为可变参数模板子生成元组?
【发布时间】:2020-02-25 19:20:46
【问题描述】:

简而言之:如何从给定类型的孩子创建可变元组?

在下面的代码中,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();
    }
};

提前致谢!

【问题讨论】:

  • 您的设计中有一些严重的object orgy...
  • 这是一个理论问题。实际上 Child 将是另一个非模板类。
  • 请注意包是T,而不是T...——省略号不是其名称的一部分,而是用于扩展类型名称或表达式条款

标签: c++ templates c++17 variadic


【解决方案1】:

因为你标记了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>
}

Demo

【讨论】:

    【解决方案2】:

    怎么样

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

    ?

    我的意思是......单一类型是T::Child,所以要重复这些类型,您必须在类型之后放置省略号(...),所以T::Child...

    但是,给定一个泛型类型TT::Child 可以是一个类型,也可以是一个成员或方法。所以你需要typename 之前通知编译器下面的T::Child 是一个类型而不是一个成员或其他。

    【讨论】:

      猜你喜欢
      • 2021-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-15
      • 1970-01-01
      • 2017-07-11
      相关资源
      最近更新 更多