类型、整型常量和模板模板参数的可变模板
Variadic templates of types, integral constants and template template parameters
我有以下问题。我有一些类执行输入数组到输出数组的映射。我想要有float类型,以及数组的长度作为模板参数,所以映射类看起来像这样:
template <typename FloatType, std::size_t input, std::size_t output>
class Mapper
{};
template <typename FloatType, std::size_t input, std::size_t output>
class FirstMapper : public Mapper<FloatType, input, output>
{};
template <typename FloatType, std::size_t input, std::size_t output>
class SecondMapper : public Mapper<FloatType, input, output>
{};
到目前为止一切顺利。我的目标是编写一个类来堆叠这些Mapper类的不同实例。我希望能够编写这样的代码:
StackedMapper<
double, // the FloatType, obviously
input_1, // the size of the first mapper's input array
FirstMapper, // the template template type of the first mapper
input_2, // the size of the first mapper's output and
// second mapper's input array
SecondMapper, // the template template type of the second mapper
input_3, // the size of the second mapper's output and
// third mapper's input array
FirstMapper, // the template template type of the third mapper
output // the size of the third mapper's output array
// ... any additional number of Mapper classes plus output sizes
> stacked_mapper;
在内部,StackedMapper
类应该在std::tuple
中存储映射器实例。我希望元组具有以下类型:
std::tuple<
FirstMapper<double, input_1, input_2>,
SecondMapper<double, input_2, input_3>,
FirstMapper<double, input_3, output>
// ...
>;
如省略号所示,我想添加任意数量的Mapper类。正如您可能从注释中看到的那样,一层的输出大小等于下一层的输入大小。对于堆栈中的所有映射器,float类型只定义一次。
有谁有主意吗?我已经看到了这个问题,它解决了交替类型(积分常数和类型)问题,但它似乎不适用于模板模板参数,因为我总是得到像expected a type, got 'FirstMapper'
这样的错误。
有人对此有什么想法吗?
下面简要介绍基于Boost.MPL的模板元编程。其本质是在所有方面都使用类,以便在代码中获得尽可能多的规律性。
首先,使用integral_constant
来包装常量。这被称为"元数据",该值包含在一个嵌套的数据成员value
中。
// nullary metafunction ("metadata"), wrap "value"
template<class T, T v>
struct integral_constant
{
using type = integral_constant<T, v>;
using value_type = T;
static constexpr auto value = v;
};
你可以使用类,包括整型常量元数据,作为"元函数"的参数:常规类模板,返回它们的值作为嵌套类型type
。
// regular metafunction: class template that takes metadata "X", returns "type" with "value" squared
template<class X>
struct square
:
integral_constant<typename X::value_type, (X::value * X::value)>
{};
为了避免在传递元函数时使用模板-模板参数,可以使用元函数类:这些是包含嵌套元函数的常规类apply
// higher-order metafunction: class that has nested metafunction "apply" which returns square
struct square_f
{
template<class X>
struct apply
:
square<X>
{};
};
要查看上述定义的有用性,通过在integral_constant<int, 2>
square_f
元函数类,可以非常直接地计算整数2
的平方和四次幂。// regular metafunction that takes higher-order metafunction "F" and metafunction "X" and returns "F<F<X>>"
template<class F, class X>
struct apply_twice
:
F::template apply<typename F::template apply<X>::type>
{};
template<class X>
struct quartic
:
apply_twice<square_f, X>
{};
int main()
{
using two = integral_constant<int, 2>;
static_assert(4 == square<two>::value, "");
static_assert(16 == quartic<two>::value, "");
}
<<p> 生活例子/strong>。要将其推广到可变模板参数,只需使用
template<class... Xs>
struct some_fun;
用于接受可变数量参数的元函数。这是一个练习。重点是通过合适的包装器将每个(数据、类、函数)参数统一地视为一个类。
注意:我使用继承来自动嵌入嵌套的type
到派生类中。这种技术被称为"元函数转发",可以减少typename F<T>::type
杂乱的数量。
- 扩展C++生成的代码的模板参数类型名称
- 如何在 c++ 中定义接受不同参数类型的函数向量?
- 在 C++ 中运行时调用模板时,是否可以切换模板的参数类型?
- 将函数参数类型声明为 auto
- 将函数的参数 - 签名从使用 'std::function<T>' 转换为模板参数类型
- 在 C++17 中调用具有不同参数类型的构造函数
- 具有先前参数类型匹配的参数包
- 我想知道为什么"std::unique_ptr<int> foo(新 int)"是合法的,因为"std::<int>unique_ptr"要求输入参数类型应该是"int"?
- 将可变参数类型列表的扩展打包为复杂类型的初始值设定项列表 - 合法吗?
- MSVC 错误:4 个重载中的任何一个都无法转换所有参数类型
- 使用constexpr + auto作为返回和参数类型的奇怪类型推导
- 如何从第一个参数推断第二个参数类型?
- C++模板函数中,指定回调函子/lambda 的参数类型,同时仍允许内联?
- 如何用不同的参数类型和数字回调函数
- C++stoi:这两个重载都无法转换所有参数类型
- 为什么std::{container}::template不能推导其参数类型
- 为模板参数类型中的新对象分配内存
- 为指向成员模板参数的指针推导额外模板参数类型的紧凑方式
- 使用std::conditional中的模板来确定函数参数类型
- C++中的短参数类型