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

use*_*759 5 c++ templates metaprogramming c++11

我想在不考虑底层结构是数组的情况下概括C++中的按位运算符.

例如......如果我想代表86位,我将使用结构结构/类,如:

typedef struct {
 uint64_t x[1];
 uint16_t y[1];
 uint8_t z[1];
} sampleStruct;
Run Code Online (Sandbox Code Playgroud)

相反,如果我想分配160位,我会使用如下结构:

typedef struct {
 uint64_t x[2];
 uint32_t y[1];
} sampleStruct;
Run Code Online (Sandbox Code Playgroud)

我认为存储的一个微不足道但不是最优的解决方案是假设所有块都是统一的并且分配最小值,它覆盖我正在实现的大小,但是即使是练习,我更喜欢我暴露的方式.

对我而言,听起来我应该使用元编程来解决问题,所以我必须正确定义

template <int I>
typedef sampleStruct {
  //something
}
Run Code Online (Sandbox Code Playgroud)

但是我不是C++模板元编程的大专家,所以我想了解实现不同类型的示例struct变量的最佳方法.我知道如何为我的长度决定最好的"封面"是这样的:

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
}
Run Code Online (Sandbox Code Playgroud)

我能做些什么来实现我想做的事情?

我还猜测,与其他可能的实现相比,正确地激励块可以实现稍微更好的性能.

希望它足够清楚......(假设C++ 11或更新的版本).

eca*_*mur 0

这是可能的,但是涉及大量的打字。问题是 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)>;
Run Code Online (Sandbox Code Playgroud)

各种部分专业化(总共 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...
Run Code Online (Sandbox Code Playgroud)

另外,由于零长度数组是非法的,如果您希望能够允许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...
Run Code Online (Sandbox Code Playgroud)

使用起来会更简单std::array<std::uint8_t, (I + 7) / 8>,可能需要一个alignas修饰符来对其进行 64 位对齐。