如果您要跟踪我的问题历史记录,我会更新维度分析库,以便抛弃宏的噩梦并学习C ++ 11,可变参数模板,元编程和功能编程范式。对于我的生活,这些东西仍然是神奇的。
无论如何,我有一些指数常量元组来定义物理单位。
template<int... I>
using make_dimension = std::tuple<std::ratio<I>...>;
using scalar_dimension = make_dimension<0, 0, 0, 0, 0, 0, 0>;
using length_dimension = make_dimension<1, 0, 0, 0, 0, 0, 0>;
using time_dimension = make_dimension<0, 0, 1, 0, 0, 0, 0>;
这是对SI单位进行建模的库的(部分)。你只能乘以不同的单位,你可以另外添加像单位和标量。这些库是花花公子的,因为如果你不恰当地混合单元,它们会导致编译时错误。有> 400个单位,其中大多数是根据其他单位定义的。乘法单位时,会添加指数,当除以单位时,会减去指数。因此,为了定义速度,我想要一种表达方式:
using velocity_dimension = divide_dimensions<length_dimension, time_dimension>;
这应该在功能上等同于写作:
using velocity_dimension = make_dimension<1, 0, -1, 0, 0, 0, 0>;
我一直在使用谷歌搜索,但我不知道要点击某些命中的术语。我发现的最接近的是一个for_each,它在运行时将一个函数应用于元组的元素......这让我大吃一惊,所以我无法弄清楚如何转向它进入元素的编译时迭代。 &#39; make_dimension&#39;刚刚在上面向我解释过,它让我大吃一惊,但我恢复了。我有点要求提供讲义,所以有没有人有任何好的资源来学习这些东西?我很难相信我是唯一一个对此感兴趣的人。
答案 0 :(得分:2)
@ dyp在注释中的解决方案使用递归实例化的模板。虽然这是可变参数模板最常用的技术之一,但在这种情况下,递归可能是过度的,因为整个转换集可以在单个包扩展中执行,同时扩展两个参数包:
template<template<class, class> class, class, class>
struct tuple_transform; // undefined
template<template<class, class> class Transform, class...Ts, class...Vs>
struct tuple_transform<Transform, std::tuple<Ts...>, std::tuple<Vs...>> {
using type = std::tuple<Transform<Ts, Vs>...>;
};
template<class T, class U>
using divide_dimensions = typename tuple_transform<std::ratio_subtract, T, U>::type;
请注意,上面假设Transform<T, U>
是所需结果类型的别名。这符合ratio_add
等行为 - 它们是生成的std::ratio
的别名模板,因此typename ratio_add<...>::type
不是必需的。
答案 1 :(得分:0)
虽然TC的答案是正确的,你可以简单地使用std::integer_sequence(这是C ++ 14,但可以简单地实现)而不是比率和元组(在我看来)不适合使用constexpr仿函数操纵。 现在你的代码应该如下所示(我没有尝试编译):
template<int... I>
using make_dimension = std::integer_sequence<int, I...>;
template<class Functor, class Dim1, class Dim2>
struct transfrom;
template<class Functor, int... Dims1, int... Dims2>
struct transform<
Functor,
std::integer_sequence<int, Dims1...>,
std::integer_sequence<int, Dims2...>
> {
static_assert(sizeof...(Dims1)==sizeof...(Dims2), "wrong dimensions");
static constexpr Functor f;
using type=std::integer_sequence<int, f(Dims1,Dims2)...>;
};
struct add {
constexpr int operator()(int l, int r) const { return l+r; }
};
struct sub {
constexpr int operator()(int l, int r) const { return l-r; }
};
template<class T, class U>
using divide_dimensions = typename transform<sub, T, U>::type;
答案 2 :(得分:-1)
我没有足够的信息,但看起来像(1,0,-2,0,0,0,0)就是加速所需要的。 1表示米,-2表示除以秒的平方,就像数学中的负指数一样。