gpt4 book ai didi

c++ - 从非常量到 const 版本的 reinterpret_cast 模板类

转载 作者:搜寻专家 更新时间:2023-10-31 00:27:21 28 4
gpt4 key购买 nike

我有模板类 ImageView<Pixel>它存储指向数据和图像大小的非拥有指针。

我想要 const 正确性,所以我同时使用 Pixelconst Pixel :

std::byte * data;
ImageView<char> img(data, width, height);
std::byte const* cdata;
ImageView<char> img(cdata, width, height); // compile error
ImageView<const char> cimg(cdata, width, height);

但是它当然会导致这样的代码出现问题:

void foo(ImageView<const char> const&);

ImageView<char> view;
foo(view); // conversion from ImageView<char> to ImageView<const char> const& required

明显的解决方案是使用构造函数添加隐式转换:

template <class = std::enable_if_t<std::is_const_v<Pixel>>>
constexpr ImageView(ImageView<std::remove_const_t<Pixel>> const& other) noexcept
: m_data(other.GetData())
, m_stride(other.GetStride())
, m_width(other.GetWidth())
, m_height(other.GetHeight())
{}

但它的缺点是每次转换都会创建临时文件并且 ImageView在大多数 64 位平台上是 24 字节。这个临时文件与原始文件的区别仅在于类型——它们具有完全相同的布局。所以我开始考虑使用reinterpret_cast和 const 引用转换运算符:

template <class = std::enable_if_t<!std::is_const_v<Pixel>>>
constexpr operator ImageView<std::add_const_t<Pixel>> const&() const noexcept
{
using ConstImageView = ImageView<std::add_const_t<Pixel>>;
return *reinterpret_cast<ConstImageView const*>(this);
}

它似乎有效,但我不确定最后一个片段的正确性。


整个类的简化版(只省略了一些额外的非虚函数):

template <class Pixel>
class ImageView
{
template <class T, class U>
using copy_const_qualifier =
std::conditional_t<
std::is_const_v<T>,
std::add_const_t<U>,
std::remove_const_t<U>>;

using Byte = copy_const_qualifier<Pixel, std::byte>;

public:

constexpr ImageView(Byte * data, unsigned w, unsigned h, std::size_t s) noexcept
: m_data(data)
, m_stride(s)
, m_width(w)
, m_height(h)
{}

constexpr Byte * GetData() const noexcept { return m_data; }
constexpr std::size_t GetStride() const noexcept { return m_stride; }
constexpr unsigned GetWidth() const noexcept { return m_width; }
constexpr unsigned GetHeight() const noexcept { return m_height; }

protected:
Byte * m_data;
std::size_t m_stride; // in bytes
unsigned m_width; // in pixels
unsigned m_height; // in pixels
};

最佳答案

是的,那个reinterpret_cast无效,您不能将一个对象强制转换为另一个不相关类型的对象。可以,但请不要在之后访问它。

您可以添加一个转换运算符,而不是禁用隐式构造函数,这是行不通的,因为您在非重载解析上下文中使用 SFINAE(有变通方法,例如使条件依赖,这将实现相同的效果目标)。但使用转换运算符更清洁 IMO:

operator ImageView<const Pixel>() { return {m_data, m_width, m_height, m_stride}; }

您不必担心复制,编译器很聪明! :) 24 个字节真的没什么好担心的。

看装配here你自己。 gcc 在 -O1 上生成相同的代码及以上通过 ImageView<const char>ImageView<char>foo , 以及上面的 clang -O2 .因此,如果您使用优化进行编译,则完全没有区别。

关于c++ - 从非常量到 const 版本的 reinterpret_cast 模板类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49490910/

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