按索引将字节插入较大的类型

时间:2019-05-15 21:42:52

标签: c++ templates c++17 masking constructor-overloading

这是我的类模板,它是其构造函数之一,它将从字节大小为T的类型N构造字节大小为P的类型M。构造函数还需要一个u8索引。

索引的工作范围如下:

// pseudo code
lower bound is >= 0 in all cases
upper bound depends on sizeof(T) & sizeof(P) therefore
if (M > N) then
    idx <= (M / N) - 1
else 
    idx <= 0;

这是类模板及其构造函数:

// Actual class implementation without the include files and 
// of the using's and other constructors.

using u8 = std::uint8_t;
// etc. u16, u32 & u64...

template<typename T> 
    struct Register {
    T data;
    T value;
    std::bitset<sizeof(T) * CHAR_BIT> bits;

    template<typename P>
    Register(const P val, const u8 idx) :
        data{ static_cast<T>((val >> std::size(bits) * idx) &
              std::numeric_limits<std::make_unsigned_t<T>>::max()) },
        value{ data },
        bits{ data }
    {
        // Reg8  From: 16 idx=[0,1], 32 idx=[0,3], 64 idx=[0,7]
        // Reg16 From: 32 idx=[0,1], 64 idx=[0,3]
        // Reg32 From: 64 idx=[0,1]

        constexpr u16 sizeT = sizeof(T);
        constexpr u16 sizeP = sizeof(P);
        assert((idx >= 0) &&  ((sizeP > sizeT) ? (idx <= ((sizeP / sizeT) - 1)) : (idx <= 0)));
    }
};

// I for got to add these:
using Reg8  = Register<u8>;
using Reg16 = Register<u16>
using Reg32 = Register<u32>
using Reg64 = Register<u64>

以下是该构造函数的基本视觉表示,为简单起见,我将使用u8u16

// pseudo code: 
// low byte always farthest to right 
// high byte always farthest to left
u16 val{ 0x69BC };

Reg8 r8a{val, 0); // get byte from index 1 or low byte
r8.value = 188
r8.value in hex = 0xBC;
r8.bits  = 1011110;

Reg8 r8b{val, 1); // get byte from index 1 or high byte
r8.value = 105;
r8.value in hex = 0x69;
r8.bits = 01101001

这适用于u8 = 1字节,u16 = 2字节,u32 = 4字节和u64 = 8字节的四种无符号int类型大小中的任何一种。


这一次,如果(M

我要调整此构造函数或创建一个重载。 我需要在这里知道的是如何弄清楚与上面相反的方法。

我将使用与上面相同的u16值:但是这一次,我们将使用索引从其构造Reg64。该索引的范围是[0,3]大于3的任何值,构造函数将声明。

u16 val{ 0x69BC };
Reg64 r64a( val, 0 );
Reg64 r64b( val, 1 );
Reg64 r64c( val, 2 );
Reg64 r64d( val, 3 );   
// Reg64 r64x(val, x > 3); Assertion Failure

在这里,我想将u16类型的值的字节模式插入到从右开始的索引为0的相应字位置中。为了简化这一过程,我将不使用二进制序列,因此我将使用十六进制表示法来表示四种情况下构造函数的作用。

// u16 val{ 0x69BC }; // visual reference
r64a.value in hex: = in bin: 0x0000 0000 0000 69BC
r64b.value in hex: = in bin: 0x0000 0000 69BC 0000
r64c.value in hex: = in bin  0x0000 69BC 0000 0000
r64d.value in hex: = in bin: 0x69BC 0000 0000 0000

r64a.bits = bin rep of above ... and so one for 46b,c&d.

因此,当我从数据成员的提取中回顾构造函数时

data{ static_cast<T>((val >> std::size(bits) * idx) &
      std::numeric_limits<std::make_unsigned_t<T>>::max()) },

和断言的条件:

assert( (idx >= 0) &&  
        ((sizeP > sizeT) ? 
            (idx <= ((sizeP / sizeT) - 1)) : 
            (idx <= 0))
      );

这两个都需要颠倒或调整。

这是我的一系列相关问题和疑虑:

  
      
  • 我能够使用相同的构造函数来执行这两个角色吗?还是我必须编写此构造函数的重载版本?
  •   
  • 至于断言公式,我可以很容易地弄清楚这一点,因此在那里没有问题。用于在给定的索引位置插入字节;这就是我在努力解决的问题。对于移位操作和布尔逻辑,这里的任何帮助将非常感激。
  •   最后,关于构造函数;与上面的原始数据一样,首先要对数据进行初始化,然后从中构造bitset。我是否必须先初始化bitset,然后相应地为其设置数据和值,还是最好使用辅助函数模板?   

0 个答案:

没有答案