【问题标题】:use the TYPE from the tempate type argument list使用模板类型参数列表中的 TYPE
【发布时间】:2016-10-24 09:37:02
【问题描述】:

我想使用类模板参数列表中的类型信息。

快速解决方法的工作示例:

struct NoParam {};
template< typename A = NoParam,
          typename B = NoParam,
          typename C = NoParam,
          typename D = NoParam,
          typename E = NoParam,
          typename F = NoParam >
struct TypeList
{
  typedef A T1;
  typedef B T2;
  typedef C T3;
  typedef D T4;
  typedef E T5;
  typedef F T6;
};

template<typename... Types>
class Application
{
   Application()
   {
      // the actual code will store the created instances in a tuple or map..
      std::make_unique< TypeList<Types...>::T1 > ();
      std::make_unique< TypeList<Types...>::T2 > ();
      std::make_unique< TypeList<Types...>::T3 > ();
      std::make_unique< TypeList<Types...>::T4 > ();
      std::make_unique< TypeList<Types...>::T5 > ();
      std::make_unique< TypeList<Types...>::T6 > ();
   }
}

有没有通用的方法...

  • 遍历类型并获取类型信息(用于创建实例)
  • 示例中仅有限的 6 种类型没有硬编码

【问题讨论】:

  • 使用可变参数模板。

标签: c++ c++11 templates c++14 variadic-functions


【解决方案1】:

不要重新发明轮子,您可以使用std::tuplestd::tuple_element_t

template<typename... T>
using TypeList = std::tuple<T...>;

template<int I, typename T>
using Type = std::tuple_element_t<I, T>;

template<typename... Types>
class Application {
    Application() {
        std::make_unique<Type<0, TypeList<Types...>>> ();
        std::make_unique<Type<1, TypeList<Types...>>> ();
        // and so on...
    }
}

现在迭代类型非常简单。
它遵循一个最小的工作示例,向您展示如何做到这一点:

#include <tuple>
#include <functional>
#include <memory>

template<typename... T>
using TypeList = std::tuple<T...>;

template<int I, typename T>
using Type = std::tuple_element_t<I, T>;

template<typename... Types>
class Application {
    using MyTypeList = TypeList<Types...>;

    template<std::size_t... I>
    void iterate(std::index_sequence<I...>) {
        // demonstration purposes, here I'm simply creating an object of the i-th type
        int _[] = { 0, (Type<I, MyTypeList>{}, 0)... };
        (void)_;
    }

public:
    void iterate() {
        iterate(std::make_index_sequence<sizeof...(Types)>{});
    }

    Application() {
        std::make_unique<Type<0, MyTypeList>> ();
        std::make_unique<Type<1, MyTypeList>> ();
        // and so on...  
    }
};

int main() {  
    Application<int, float> app;
    app.iterate();
}

请注意,std::index_sequencestd::make_index_sequence 从 C++14 开始可用。无论如何,如果你受限于 C++11,你可以在网上找到几个可以使用的实现。
否则,您还可以使用几个递归 _sfinae'd_functions 来迭代类型,检查是否已达到 sizeof...(Types)

【讨论】:

  • 如果我想使用每种类型来创建容器,我该怎么做? std::vector> ??
  • 这取决于你想用这些容器做什么。如果您可以给我更多详细信息,我将在答案中添加一个示例...
  • 我明白了。我现在知道如何使用它们了。但是 braced-init-list { 0, ( (void) XXXX, 0) ... } 的技巧对我来说是新的。我可以在 google 中进一步研究什么关键字?
  • 这是一个扩展包。我想您可以找到更多详细信息here
【解决方案2】:

你可以避免使用类似的结构 typeList 索引可变参数类型

struct noTypeInList
 { };

template <std::size_t, typename ...>
struct typeSel;

template <typename T0, typename ... Ts>
struct typeSel<0U, T0, Ts...>
 { using type = T0; };

template <std::size_t N, typename T0, typename ... Ts>
struct typeSel<N, T0, Ts...>
 { using type = typename typeSel<N-1U, Ts...>::type; };

template <std::size_t N>
struct typeSel<N>
 { using type = noTypeInList; };

所以

std::make_unique< TypeList<Types...>::T1 > ();

成为

std::make_unique< typeSel<0, Types...>::type > ();

以下是完整的 C++11 示例,以防您想要 std::tuplestd:unique_ptr

#include <tuple>
#include <memory>

struct noTypeInList
 { };

template <std::size_t, typename ...>
struct typeSel;

template <typename T0, typename ... Ts>
struct typeSel<0U, T0, Ts...>
 { using type = T0; };

template <std::size_t N, typename T0, typename ... Ts>
struct typeSel<N, T0, Ts...>
 { using type = typename typeSel<N-1U, Ts...>::type; };

template <std::size_t N>
struct typeSel<N>
 { using type = noTypeInList; };

template <std::size_t ...>
struct range
 { };

template <std::size_t N, std::size_t ... Next>
struct rangeH 
 { using type = typename rangeH<N-1U, N-1U, Next ... >::type; };

template <std::size_t ... Next >
struct rangeH<0U, Next ... >
 { using type = range<Next ... >; };

template<typename... Types>
class Application
 {
   private:
      std::tuple<std::unique_ptr<Types>...> tpl;

      template <std::size_t ... rng>
      Application (const range<rng...> &)
         : tpl{std::make_tuple(std::unique_ptr<
                  typename typeSel<rng, Types...>::type>()...)}
          { }

   public:
      Application () : Application(typename rangeH<sizeof...(Types)>::type())
       { }
 };

int main()
 {
   Application<int, float, int, std::tuple<double, long>>  a;
 }

这只是typeSel 的使用示例,因为Application 可以简单地写成

template<typename... Types>
class Application
 {
   private:
      std::tuple<std::unique_ptr<Types>...> tpl;

   public:
      Application () : tpl{std::make_tuple(std::unique_ptr<Types>()...)}
       { }
 };

如果你可以使用C++14编译器,你可以使用std::index_sequencestd::make_index_sequence(并删除rangerangeH)和Application可以变成

template<typename... Types>
class Application
 {
   private:
      std::tuple<std::unique_ptr<Types>...> tpl;

      template <std::size_t ... rng>
      Application (const std::index_sequence<rng...> &)
         : tpl{std::make_tuple(std::unique_ptr<
                  typename typeSel<rng, Types...>::type>()...)}
          { }

   public:
      Application () : Application(std::make_index_sequence<sizeof...(Types)>())
       { }
 };

【讨论】:

    【解决方案3】:

    最简单最干净的方法,使用递归模板类

    template<class...> class Application;
    
    template<class T> class Application<T>{
      public:
       Application()
       {
          std::make_unique<T> ();
       }
    };
    template<class T,class...Others> class Application<T,Others...>
                            :  public Application<Others...>{
      public:
       Application():Application<Others...>()
       {
          std::make_unique<T> ();
       }
    };
    

    【讨论】:

      猜你喜欢
      • 2011-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      • 2015-08-06
      相关资源
      最近更新 更多