提问人:Stefano Bellotti 提问时间:10/25/2023 最后编辑:Stefano Bellotti 更新时间:10/25/2023 访问量:86
在具有兼容布局的 std::vector 底层缓冲区上使用 std::bit_cast
Using std::bit_cast on a std::vector underlying buffer with compatible layout
问:
我需要使用 C++ 库中不同类型实体的整数标识符包装 C 库。 我希望通过我的库同时实现类型安全性和效率(理想情况下是零开销)。
本机 C 库具有类似于以下内容的功能:
int ps_get_bodies_bounds(int const* bodies, int size, ...);
int ps_get_faces_bounds(int const* faces, int size, ...);
正如你所看到的,s到处都被用来表示各种实体。int
在我的 C++ 库中,我想使用类型系统来表达这些不同的实体:
class Body
{
public:
constexpr Body() noexcept
{
// enforce at compile time that this class
// must be just a strongly typed integer
static_assert(sizeof(Body) == sizeof(int));
}
// ... public API ...
private:
int m_tag{ 0 };
};
class Face
{
// similar to what has been done for 'Body'
};
C++包装器的目标之一是客户端可以使用连续的内存容器,例如存储实体并对其进行操作:std::vector
wrapper::Bounds wrapper::get_bounds(std::vector<Body> const& bodies);
wrapper::Bounds wrapper::get_bounds(std::vector<Face> const& faces);
包装器当然应该调用底层 C 函数,理想情况下,出于效率原因,我希望能够直接传递向量持有的内存:
wrapper::Bounds wrapper::get_bounds(std::vector<Body> const& bodies)
{
// ...
// OF COURSE, DOES NOT COMPILE
auto err = ps_get_bodies_bounds(bodies.data(), static_cast<int>(bodies.size()), ...);
// ...
}
以这种方式编写,代码当然不会编译,因为返回的是类型而不是.bodies.data()
Body const*
int const*
在这种情况下,它是否是一种定义明确的行为/安全/可移植?std::bit_cast
ps_get_bodies_bounds(std::bit_cast<int const*>bodies.data(), ...);
如果是,它甚至适用于像 ?std::span<Body>
请注意,我在编译时强制 、 等的大小......匹配 .Body
Face
int
我已经在带有 GCC、Clang 和 MSVC 的编译器资源管理器上尝试了这种方法,它似乎有效(代码比我在这里解释的要复杂一些,但核心概念是相同的)。我不确定它是否是 UB 的有效使用。这是 Godbolt 的链接:https://godbolt.org/z/44GWc7PYs。std::bit_cast
提前感谢您的帮助。
答: 暂无答案
评论
bit_cast
Body
int
reinterpret_cast<int const*>(bodies.data())
start_lifetime_as
和start_lifetime_as_array
函数,这将明确支持重新解释强制转换的使用。如果您使用 C++23 或计划迁移,则可以使用它。vector