【问题标题】:nested templates (template template parameters)嵌套模板(模板模板参数)
【发布时间】:2016-08-22 11:23:51
【问题描述】:

如何编写一个接受嵌套模板的模板函数?

例如,我想编写以下函数:

void print(const T1<T2<T3>> &container);

试过了:

template<
  template<typename> class T1,
  template<typename> class T2,
  class T3
>
void print(const T1<T2<T3>> &container) {
  for (auto &e : container)
    for (auto x : e)
      std::cout<<e<<' ';
  std::cout<<'\n';
}

int main()
{
  std::vector<std::deque<int>> c = {{1,2},{3}};
  print(c);
  return 0;
}

g++ 编译错误:

a.cc: In function ‘int main()’:
a.cc:23:14: error: no matching function for call to ‘print(std::vector<std::deque<int> >&)’
       print(c);
              ^
a.cc:12:10: note: candidate: template<template<class> class T1, template<class> class T2, class T3> void print(const T1<T2<T3> >&)
     void print(const T1<T2<T3>> &container) {
          ^
a.cc:12:10: note:   template argument deduction/substitution failed:
a.cc:23:14: error: wrong number of template arguments (2, should be 1)
       print(c);
              ^
a.cc:8:32: note: provided for ‘template<class> class T1’
       template<typename> class T1,
                                ^

来自 Clang 的编译错误:

a.cc:23:7: error: no matching function for call to 'print'
      print(c);
      ^~~~~
a.cc:12:10: note: candidate template ignored: substitution failure : template template argument has different template parameters than its corresponding
      template template parameter
    void print(const T1<T2<T3>> &container) {
         ^

也试过了:

template<
  template<template<typename> class> class T1,
  template<typename> class T2,
  class T3
>
void print(const T1<T2<T3>> &container);

但是在推演之前还是有编译错误:

a.cc:12:25: error: template argument for template template parameter must be a class template or type alias template
    void print(const T1<T2<T3>> &container) {
                        ^

---- 编辑----

如果我想返回指向其中一种类型的指针怎么办?

 T3 get(const T1<T2<T3>> &container);

【问题讨论】:

标签: c++ templates


【解决方案1】:

不过,我更喜欢您使用单个模板并从中选择 typedef。

类似:

template<typename T1>
void print(const T1& container) { //As opposed to const T1<T2<T3>> &container
    using T2 = typename T1::value_type;
    using T3 = typename T2::value_type;

  for (auto &e : container)
    for (auto x : e)
      std::cout<<x<<' ';
  std::cout<<'\n';
}

但如果你必须按照自己的方式行事,那么这将起作用std::vectorstd::deque 实际上是用两个模板参数声明的,尽管分配器是默认的)

template<
  template<typename, typename> class T1,
  template<typename, typename> class T2,
  typename AllocT1, typename AllocT2, 
  typename T3
>
void print(const T1<T2<T3, AllocT2>, AllocT1> &container) {
  for (auto &e : container)
    for (auto x : e)
      std::cout<<x<<' ';
  std::cout<<'\n';
}

但是有一个更简洁的解决方案:

template<typename T1, 
         typename T2 = typename T1::value_type,
         typename T3 = typename T2::value_type>
T3 print(const T1& container){

  for (auto &e : container)
    for (auto x : e)
      std::cout<<x<<' ';
  std::cout<<'\n';

  return T3();
}

选择权在您手中。 :-)

编辑:

如果我想返回指向其中一种类型的指针怎么办?

T3 get(const T1<T2<T3>> &container);

在 C++14 中,您可以简单地使用 auto 占位符返回类型,或者使用上面的后一种解决方案。

【讨论】:

  • 我会使用Args1... 来代替typename...typename 来代替Alloc1
  • @Jarod42,是的,因为它只有一个模板参数......有道理。谢谢贾罗德。改进了!
  • 我更喜欢第一个,但实际上我需要使用其中一种类型作为返回值,例如T3 get(const T1&lt;T2&lt;T3&gt;&gt; &amp;container);你知道这样写吗?
  • @Deqing,请看我更新的答案(第三个代码 sn-p)
  • 谢谢,很有帮助。
【解决方案2】:

单个模板参数将为您工作:

template<class T>
void print(const T& container) {
  for (auto &e : container)
    for (auto x : e) std::cout << x << ' ';
  std::cout << '\n';
}

Live Demo

【讨论】:

  • 可能会添加一些检查以使错误消息更加清晰(一些静态断言)。
猜你喜欢
  • 2018-11-26
  • 1970-01-01
  • 2012-12-06
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-01
相关资源
最近更新 更多