在c++中,是否可以不使用结构体而声明一个具有设置位宽的类型?

rqenqsqc  于 2023-07-01  发布在  其他
关注(0)|答案(1)|浏览(165)

自从我上次接触C以来,至少已经有十年了。据说,C已经有了一个小小的改革。有没有一种方法可以指定类型的位宽,而不使用结构、类或联合位域?它们的问题是,它增加了一个不必要的和恼人的间接级别:

struct Address
  {
        unsigned char val:4 = 0; // C++ in 2020?
  };

  struct Device
  {
        Address address;    // 4-bit address
        string name;
  };

  int main() 
  {
        Device device;
        device.address.val = 0x8;  // Yuckity yuck WTF!
        return 0;
  };

如果C++有像C#一样的属性,你可以让Address成为一个访问器来隐藏间接寻址。在Ada中,您只需像这样声明Address

type Address is range 0..2**4 - 1 with Object_Size = 4;  -- Isn't this cute and sweet!

我尝试了下面的声明,没有理由不工作:

typedef unsigned char Address:4;   // if we were only so lucky!

C++是否支持这样的构造或解决方法?

gxwragnw

gxwragnw1#

不是开箱即用的,但是创建一个执行验证的小 Package 器类并不难。这里简单的画了这样一个类,它甚至可以在编译时检查.
示例:https://onlinegdb.com/RBVQfsAI5

#include <iostream>

// N is the number of address bits you want to use
template<std::size_t N>
struct address_t
{
public:
    explicit constexpr address_t(std::uintptr_t value) :
        address{ checked_value(value) }
    {
    }

    // one of the rare cases implicit conversion is useful
    operator std::uintptr_t() const noexcept
    {
        return address;
    }

    // assigment operator checks the value.
    void operator=(std::uintptr_t value)
    {
        address = checked_value(value);
    }

private:
    constexpr std::uintptr_t checked_value(std::uintptr_t value)
    {
        if (value >= (1 << N)) throw std::invalid_argument("address value too large");
        return value;
    }

    std::uintptr_t address;
};

int main()
{
    //addres_t<4> means an address with max. 4 bits
    static constexpr address_t<4> compile_time_address{15}; // will not compile if value too big
    std::cout << compile_time_address << "\n"; // uses implicit conversion to std::uint_ptr_t

    address_t<4> runtime_address{15};
    std::cout << runtime_address << "\n";
    runtime_address = 12;
    std::cout << runtime_address << "\n";

    try
    {
        // at runtime assigning an invalid value will throw.
        address_t<4> runtime_address_fail{16};
    }
    catch (const std::invalid_argument&)
    {
    }

    return 0;
}

相关问题