[英]Metaprogramming for optimizing storage/run time algorithm, C++
我想在不考虑底层结构是数组的情况下概括C ++中的按位运算符。
例如......如果我想代表86位,我将使用结构结构/类,如:
typedef struct {
uint64_t x[1];
uint16_t y[1];
uint8_t z[1];
} sampleStruct;
相反,如果我想分配160位,我会使用如下结构:
typedef struct {
uint64_t x[2];
uint32_t y[1];
} sampleStruct;
我认为存储的一个微不足道但不是最优的解决方案是假设所有块都是统一的并且分配最小的那些它覆盖我正在实现的大小,但是即使对于练习而言我更喜欢我暴露的方式。
对我而言,听起来我应该使用元编程来解决问题,所以我必须正确定义
template <int I>
typedef sampleStruct {
//something
}
但是我不是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
}
我能做些什么来实现我想做的事情?
我还猜测,与其他可能的实现相比,正确地激励块可以实现稍微更好的性能。
希望它足够清楚......(假设C ++ 11或更新的版本)。
这是可能的,但涉及到相当多的打字。 问题是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)>;
各种部分特化(总共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...
此外,由于零长度数组是非法的,如果您希望能够允许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...
使用std::array<std::uint8_t, (I + 7) / 8>
可能会更直接,可能使用alignas
修饰符进行64位对齐。
使用uint8_t
数组不是更容易,例如:
template <int I>
struct sampleStruct {
std::uint8_t v[(I % 8)? (I / 8) + 1 : (I / 8)];
};
正如你提到的那样,我假设你没有访问单个成员x,y,z
,(从问题中你不会清楚如何访问基础位......)
也可以做你想要的,但你必须使用继承,如下所示:
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)> {
};
现在你的操作必须在调用基础对象方面实现......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.