简体   繁体   English

元编程用于优化存储/运行时算法,C ++

[英]Metaprogramming for optimizing storage/run time algorithm, C++

I'd like to generalize bitwise operators in C++ without thinking that the underlying structure is an array. 我想在不考虑底层结构是数组的情况下概括C ++中的按位运算符。

As instance... if I want to represent 86 bits i would use a structure structure/class like: 例如......如果我想代表86位,我将使用结构结构/类,如:

typedef struct {
 uint64_t x[1];
 uint16_t y[1];
 uint8_t z[1];
} sampleStruct;

Instead if i would like to allocate 160 bits I would use a structure like: 相反,如果我想分配160位,我会使用如下结构:

typedef struct {
 uint64_t x[2];
 uint32_t y[1];
} sampleStruct;

I guess a trivial, but not optimal solution for the storage would be to assume all chunks are uniform and allocate the minimum of those st it covers the size I'm implementing, however even for a matter of exercise I prefer the way I exposed. 我认为存储的一个微不足道但不是最优的解决方案是假设所有块都是统一的并且分配最小的那些它覆盖我正在实现的大小,但是即使对于练习而言我更喜欢我暴露的方式。

To me it sounds clear that I should use metaprogramming to solve the problem, so I have to properly define 对我而言,听起来我应该使用元编程来解决问题,所以我必须正确定义

template <int I>
typedef sampleStruct {
  //something
}

However I'm not a big expert on C++ template metaprogramming so i would like to understand what would be the best way to implement the different kind of sample struct varing I. I know how to decide the best "cover" for my length it would be something like: 但是我不是C ++模板元编程的大专家,所以我想了解实现不同类型的示例结构变量的最佳方法。我知道如何为我的长度决定最好的“覆盖”它会是这样的:

N64 = I/64;
RemN = I%64;
if(0 < RemN <= 8) {
  add uint8_t var;
} else if (8 < RemN <= 16) {
  add uint16_t var;
} else if (16 < RemN <= 24) {
  add uint16_t var;
  add uint8_t var;
} else {
  //Similarly handle the other cases from 24 < RemN < 64
}

What can I do to achieve what I want to do? 我能做些什么来实现我想做的事情?

I also guess that arraging chunks correctly would allow to achieve slightly better performance compared to other possible implementation. 我还猜测,与其他可能的实现相比,正确地激励块可以实现稍微更好的性能。

Hoping it is clear enough... (Assume C++11 or more recent versions). 希望它足够清楚......(假设C ++ 11或更新的版本)。

It's possible, but there's a fair amount of typing involved. 这是可能的,但涉及到相当多的打字。 The problem is that C++ doesn't provide a way to meta-programmatically omit a data member (see eg Conditional Inclusion/Exclusion of Data Members Inside Class Templates ) so you have to specialize on its presence or absence: 问题是C ++没有提供以元编程方式省略数据成员的方法(参见例如条件包含/排除类模板中的数据成员 ),因此您必须专注于其存在或不存在:

template<int N64, bool P32, bool P16, bool P8>
struct sampleStructImpl;

template<int I>
using sampleStruct = sampleStructImpl<I/64, (I%64 >= 32), (I%32 >= 16), (I%16 >= 8)>;

The various partial specializations (8 in total) would look like the following: 各种部分特化(总共8个)如下所示:

template<int N64>
struct sampleStructImpl<N64, true, true, true>
{
  std::uint64_t x[N64];
  std::uint32_t y;
  std::uint16_t z;
  std::uint8_t w;
};

template<int N64>
struct sampleStructImpl<N64, true, true, false>
{
  std::uint64_t x[N64];
  std::uint32_t y;
  std::uint16_t z;
  // omit std::uint8_t w;
};

// 6 more partial specializations...

Also, since zero-length arrays are illegal, if you want to be able to allow values of I less than 64 you'll have to specialize on N64 being zero: 此外,由于零长度数组是非法的,如果您希望能够允许I小于64的值,则必须专注于N64为零:

template<>
struct sampleStructImpl<0, true, true, true>
{
  // omit std::uint64_t x[0];
  std::uint32_t y;
  std::uint16_t z;
  std::uint8_t w;
};

// 7 more specializations...

It'd be a lot more straightforward to use std::array<std::uint8_t, (I + 7) / 8> , possibly with an alignas modifier to 64-bit align it. 使用std::array<std::uint8_t, (I + 7) / 8>可能会更直接,可能使用alignas修饰符进行64位对齐。

Wouldn't it be easier to use just an array of uint8_t , for example: 使用uint8_t数组不是更容易,例如:

template <int I>
struct sampleStruct {
  std::uint8_t v[(I % 8)? (I / 8) + 1 : (I / 8)];
};

As you mentioned bits, I'm assuming that you don't access the individual members x,y,z , (it's not clear from the question how you would access the underlying bits..) 正如你提到的那样,我假设你没有访问单个成员x,y,z ,(从问题中你不会清楚如何访问基础位......)

It's possible to do what you want as well, but you have to use inheritance, as follows: 也可以做你想要的,但你必须使用继承,如下所示:

template <int I>
struct largeBlock {
    std::uint64_t x[I];
};
template <>
struct largeBlock<0> {
};

template <int I>
struct mediumBlock {
    std::uint16_t y[I];
};
template <>
struct mediumBlock<0> {
};

template <int I>
struct smallBlock {
    std::uint8_t z[(I / 8) + ((I % 8) ? 1 : 0) ];
};
template <>
struct smallBlock<0> {
};

template <int I>
struct sampleStruct : largeBlock<I / 64>, mediumBlock<(I % 64) / 16>, smallBlock<(I % 16)> {

};

Now your operations have to be implemented in terms of calls to the base objects... 现在你的操作必须在调用基础对象方面实现......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM