gpt4 book ai didi

c++ - 如何创建快速 const 正确的缓冲区包装类 C++?

转载 作者:行者123 更新时间:2023-11-28 05:50:09 25 4
gpt4 key购买 nike

关闭。这个问题需要details or clarity .它目前不接受答案。












想改进这个问题?通过 editing this post 添加详细信息并澄清问题.

5年前关闭。




Improve this question




如何为现有对象创建一个包装类,它会自动禁止或允许修改包装对象的数据,具体取决于是否将包装对象提供给带有或不带有 const 类型限定符的构造函数。

因此,如果接收到包装类 (WrappedObj *ptr),则它允许设置和获取方法。如果收到包装类 (const WrappedObj *ptr),则在编译时只允许获取方法。

问题示例:

我有一个指向存在以太网 header 的缓冲区的指针,我想简化对以太网数据的访问以提高可读性并减少字节序错误。

struct ethhdr {
uint8_t h_dst[6]; /* destination eth addr */
uint8_t h_src[6]; /* source ether addr */
uint16_t h_proto; /* packet type ID field */
uint8_t h_data[0];
} __attribute__((packed));

// My wrapper "view" class, which doesn't really work as expected
class EtherView {
public:
EtherView(uint8_t *ptr) : mPtr{(ethhdr*)ptr} {}
EtherView(const uint8_t *ptr) : mPtr{(ethhdr*)ptr} {}

/* SET METHODS */
void setProtocol(uint16_t proto) {
mPtr->h_proto = htons(proto);
}
/* ........ */

/* CONST GET METHODS */
uint16_t protocol() const {
return ntohs(mPtr->h_proto);
}
/* ........ */

private:
ethhdr *mPtr;
};

int main() {
uint8_t fakeBuffer[128];
EtherView ethView(fakeBuffer);
//OK - we want to modify because fakeBuffer isn't const
ethView.setProtocol(80);

const uint8_t *fakeConstBuff = fakeBuffer;
EtherView constEthView(fakeConstBuff);
// HERE I WANT COMPILE ERROR, because Wrapper was created with const param
constEthView.setProtocol(80);

/* I know its possible to define const wrapper:
const EtherView constEthView(fakeConstBuff);
, but I do not trust to "remember" to do it - it must be automatic. */

return 0;
}

如您所见,此包装器为缓冲区修改/读取提供了安全且重要的快速包装器。我已经测试过,它具有与内联完成缓冲区值修改相同的性能(因为它们是由编译器内联的)。

到目前为止可能的(不完美的)解决方案:

1)记住为包装类添加const,当const数据源时。
  • 不想“记住”(最终会犯错)

  • 2) 使用 getter 创建基类 (EthViewConst) 并仅在 const 源上构造。然后继承该类,该类在非常量源上构造并且还具有 setter 功能。如果没有任何其他解决方案,那么这可能是做到这一点的“最佳”方式,但是:
  • 确实不符合要求。我想上一节课,但如果不可能,那么它可以接受。

  • 3)有一些特殊的工厂,它根据数据源创建常量或非常量对象。 “伪代码”示例:
    [EtherView view = EtherView::Create(buffer);],但我似乎找不到办法,因为:
  • 返回 const 或非 const 动态创建的 Wrapper 类指针可以工作,但不符合要求:它必须快。在这种情况下,这将是相当大的成本。
  • 返回 const/non-const 对象不起作用,因为“接收者”可以定义非常量对象,并且复制构造会丢失常量
  • 不能为非常量对象返回引用(因为是临时的)。也许有一些hacky方式?

  • 4)......任何其他解决方案......??
  • 搬家施工?
  • 完美转发?
  • 模板?
  • 常量表达式?
  • 预处理器 - 不,谢谢
  • 最佳答案

    这可能是对模板机制的完全滥用,并且您的里程将根据是否生成未使用的模板方法以及链接器如何处理它们而有所不同。我会说以下内容很可能不便携,而且可能很疯狂。幸运的是,如果移植不好,您可以隐藏某些类型别名以确保安全。

    如果您使用 const uint16_t*,此方法会发出非常响亮的提示。在 View 的可变版本中,或 uint16_t*在 View 的 const 版本中。

    #include <type_traits>

    struct ethhdr {
    uint8_t h_dst[6]; /* destination eth addr */
    uint8_t h_src[6]; /* source ether addr */
    uint16_t h_proto; /* packet type ID field */
    uint8_t h_data[0];
    } __attribute__((packed));


    template<typename T, typename U>
    class EtherView {
    public:
    EtherView(T* ptr) : mPtr{(U*)ptr} {}

    /* SET METHODS */
    void setProtocol(T proto) {
    mPtr->h_proto = proto;
    }

    /* CONST GET METHODS */
    T protocol() const {
    return mPtr->h_proto;
    }
    private:
    U *mPtr;
    };

    using MutableEtherView = EtherView<uint16_t, ethhdr>;
    using ConstEtherView = EtherView<const uint16_t, const ethhdr>;

    int main() {
    uint8_t fakeBuffer[128];
    MutableEtherView ethView(fakeBuffer);
    ethView.setProtocol(80);

    const uint8_t *fakeConstBuff = fakeBuffer;
    ConstEtherView constEthView(fakeConstBuff);
    MutableEtherView mutView(fakeConstBuff); // Generates error here
    constEthView.setProtocol(80); // Generates error here

    return 0;
    }

    关于c++ - 如何创建快速 const 正确的缓冲区包装类 C++?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35420321/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com