【问题标题】:template class wrapping a arbitrary type/non-type template class包装任意类型/非类型模板类的模板类
【发布时间】:2018-12-05 23:21:59
【问题描述】:

假设我有一个模板类base 和一个类wrapper,其中包含base 的实例化成员。我想定义类wrapper,使其依赖于模板参数包,该模板参数包简单地“传递”给base的实例化成员。

例如考虑下面的代码,它工作正常。

#include <iostream>

template <int i, int j>
struct base {
  base()
  {
    std::cout << "i is " << i;
    std::cout << " j is " << j << std::endl;
  }
};

template <int... T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<2, 3> x;
  return 0;
}

事先知道base的所有模板参数都是int,我在wrapper的声明中使用了template &lt;int...T&gt;。这允许有限的灵活性,例如我可以为base 的模板参数定义一些默认值,而无需修改wrapper

但是,如果base 依赖于类型和非类型模板参数的任意列表,我如何将wrapper 的模板参数传递给base

例如,如果我知道base 的所有模板参数都可以隐式转换为int(不会丢失!),我可以在下面的程序中定义wrapper

#include <iostream>

template <int i, bool j>
struct base {
  base()
  {
    std::cout << "i is " << i;
    std::cout << " j is " << (j ? "true" : "false") << std::endl;
  }
};

template <int... T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<2, true> x;
  return 0;
}

但是如果base像下面的程序一样同时依赖于类型和非类型模板参数,显然不可能简单地将wrapper的模板参数传递给base

#include <iostream>

template <class U, int i, int j>
struct base {
  base()
  {
    std::cout << "i is " << i;
    std::cout << " j is " << j << std::endl;
  }
};

template <class... T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<int, 2, 3> x; // Error!
  return 0;
}

此程序无法编译,因为编译器需要 wrapper 的类型。

有没有办法编写一个类wrapper,将其模板参数“传递”给base 类型的成员,不管它们是什么

我们的想法是为wrapper 提供一个通用代码,如果base 的模板签名发生变化,则不需要修改它。

【问题讨论】:

  • base 是否在您的控制之下?因为如果是,我们可以约束它的模板参数列表,让wrapper更容易写。
  • AFAIK 无法完成。对于每个标识符,编译器必须知道它们是类型名称还是表达式。这也是为什么你必须为依赖名称写typename
  • @NickyC 是的,我自己编程base。如果可能,我希望保留扩展/更改base 的灵活性,而无需更新wrapper
  • base不要使用非类型参数,把std::integral_constant换行。
  • “有没有办法编写一个类包装器,将其模板参数“传递”给 base 类型的成员,不管它们是什么? - 没有。

标签: c++ templates


【解决方案1】:

您的问题有解决方案。它不是很优雅,需要特定的方法,但适用于您想要的情况:

template <class U, class i, class j>
struct base {
  base()
  {
    std::cout << "i is " << i::value;
    std::cout << " j is " << j::value << std::endl;
  }
};

template <class ...T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<int, std::integral_constant<int, 2>, std::integral_constant<int, 3>> x; //no error now!
  return 0;
}

使用 C++17 可以不那么冗长:

template<auto val>
using value_wrapper = std::integral_constant<decltype(val), val>;

int main()
{
  wrapper<int, value_wrapper<2>, value_wrapper<3>> x; //no error now!
  return 0;
}

【讨论】:

  • 这当然有其局限性 从技术角度来说,它是行不通的。 base 取决于类型和非类型模板参数的任意列表 此框未选中,它是唯一 框。
  • @n.m.你是对的,我问错了。我正在修复答案 atm
  • 感谢您的努力!我会将其标记为解决方案
猜你喜欢
  • 2015-04-04
  • 2012-01-24
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多