将类似数组的对象作为模板值参数

Put array-like object as template value argument

本文关键字:值参 参数 对象 数组      更新时间:2023-10-16

我想实现

template<class ValueType,UnitTag x>
clsas Quantity;

这样的操作员
template<UnitTag y>
Quantity<T,x+y> operator*(Quantity<T,y> b)
    {return Quantity<T,x+y>(m_value*b.value());}

(也可以添加数量,但只有相同的数量)

必须完成 UnitTag s的操作,以完成元素

x_0 + y_0 = z_0
x_1 + y_1 = z_1
x_2 + y_2 = z_2
x_3 + y_3 = z_3
...

最直接的方法是让UnitTag成为一个constexpr数组。但这不能用作模板参数。作为解决方法,我可以使用大整数类型进行操作,并使用少量的位来表示每个维度。但是,这给出了尺寸数量或每个维度的功率的限制:例如,使用64位和16个维度,我只覆盖[l^( - 8),l^7]。这对于大多数应用程序应该是有益的,但是班级无法处理激进分子,因为这需要分数权力。

是否有任何方法可以在模板参数中传递超过64位信息?例如,是否可以在模板参数包上进行元素操作?元素操作是:

  • 加法(用于乘法)
  • 减法(用于分裂)

激进分子:

  • division(这需要元素像理性数字一样行为。可以使用constexpr word()访问者实现为类)

我尝试根据

提出解决方案

是否可以在模板参数包上进行元素操作?

不确定(我不知道您确切想对此值做什么),但是如果您将模板参数包包装在std::integer_sequence(或std::index_sequence,如果可以使用std::size_t),则似乎可以对我。

不幸的是,std::integer_sequencestd::index_sequence是C 14个功能。但是,如果您需要在C 11中,那么实现类似的功能很容易。

以下是使用std::index_sequence

的示例

- 编辑 - 修改的示例添加减法/除法

#include <utility>
#include <type_traits>
template <typename, typename>
struct addVI;
template <std::size_t ... Is, std::size_t ... Js>
struct addVI<std::index_sequence<Is...>, std::index_sequence<Js...>>
 {
   static_assert(sizeof...(Is) == sizeof...(Js), "! add");
   using type = std::index_sequence<(Is+Js)...>;
 };
template <typename, typename>
struct subVI;
template <std::size_t ... Is, std::size_t ... Js>
struct subVI<std::index_sequence<Is...>, std::index_sequence<Js...>>
 {
   static_assert(sizeof...(Is) == sizeof...(Js), "! sub");
   using type = std::index_sequence<(Is-Js)...>;
 };
template <typename, typename>
struct foo;
template <typename T, std::size_t ... Is>
struct foo<T, std::index_sequence<Is...>>
 {
   template <std::size_t ... Js>
   using Ks = typename addVI<std::index_sequence<Is...>,
                             std::index_sequence<Js...>>::type;
   template <std::size_t ... Js>
   using Ls = typename subVI<std::index_sequence<Is...>,
                             std::index_sequence<Js...>>::type;
   template <std::size_t ... Js>
   foo<T, Ks<Js...>> operator* (foo<T, std::index_sequence<Js...>> const & b)
    { return foo<T, Ks<Js...>>(); }
   template <std::size_t ... Js>
   foo<T, Ls<Js...>> operator/ (foo<T, std::index_sequence<Js...>> const & b)
    { return foo<T, Ls<Js...>>(); }
 };
int main ()
 {
   foo<int, std::index_sequence<1, 2, 3>> f1;
   foo<int, std::index_sequence<2, 3, 5>> f2;
   static_assert(std::is_same<decltype(f1*f2),
                              foo<int, std::index_sequence<3, 5, 8>>>::value,
                 "!!");
   static_assert(std::is_same<decltype(f2/f1),
                              foo<int, std::index_sequence<1, 1, 2>>>::value,
                 "!!!");
 }

只需通过几个整数参数。

作为替代方案,请探讨亚伯拉罕和古尔图沃伊的" C 模板元编程"。他们将此想法称为"维度分析",并使用UnitTag的类型列表。

typedef mpl::vector_c<int,0,1,0,0,0,0,0> length;
typedef mpl::vector_c<int,0,0,1,0,0,0,0> si_time;
...
typedef mpl::vector_c<int,0,1,-1,0,0,0,0> velocity;
...

标签的乘法运算符D1D2制作类型列表

typename mpl::transform<D1,D2,mpl::plus<_1,_2> >::type