以下函数模板尝试在字节数组中定位对象。 我们可以假设参数
buffer
“通常”持有给定类型的对象,但我需要针对可能的错误进行诊断(断言检查)。
template <typename T>
T* get_object_from_buffer(std::uint8_t* buffer, std::size_t size)
{
// EDIT: This constraint was missing in original version of the question.
if (size != sizeof(T))
{
// Invalid usage of the function.
return nullptr;
}
void* tmp_buffer = buffer;
if (nullptr != std::align( alignof(T),
sizeof(T),
tmp_buffer,
size ) )
{
return reinterpret_cast<T*>(buffer);
}
else
{
// Caller can check returned pointer to implement diagnostic reactions
return nullptr;
}
}
问题:
std::align
来执行此操作?
您是否看到更好的解决方案 - 更健壮、更优雅?
条件:
该功能将在嵌入式系统上使用。 因此,一些关于 PC 平台上 std::align 使用的 google 搜索结果不适用。
缓冲区由如下函数填充:
template <typename T>
std::pair<std::uint8_t*, std::size_t> put_object_into_buffer(T* object)
{
return std::pair<std::uint8_t*, std::size_t>(
reinterpret_cast<std::uint8_t*>(object),
sizeof(object)
);
}
在 put/get 函数之间,我必须通过一个不是的库传递缓冲区 了解用户定义的类型,例如
T
。
编辑/更新:
uint8_t*
和size_t
的缓冲区表示仅用于保存单个T
对象。原始问题帖子中缺少此内容。
我添加了检查,确保 size
参数实际上与对象的大小匹配。
如果没有此检查,
std::align()
可以轻松地在 T*
中找到对齐的 buffer
,因此该标准不再相关。
感谢 Ted Lyngmo 指出了这一点!
答案受到@Ted Lyngmo 的评论启发 - 请参阅问题评论
针对
size == sizeof(T)
的检查至关重要。
否则
std::align()
不会回来nullptr
每当 size
超出未对齐的 buffer
指针时
允许放置整个、对齐的 T
实例
介于 &(buffer[0])
和 &(buffer[size-1])
之间。
在错误情况下使用
nullptr
函数返回值,
没有必要区分 buffer
和 tmp_buffer
如果返回值是 std::align()
的类型转换。
那么,函数可以缩短:
template <typename T>
T* get_object_from_buffer(std::uint8_t* buffer, std::size_t size)
{
if (size != sizeof(T))
{
// Invalid usage of the function.
// Caller shall check returned pointer to implement diagnostic reactions
return nullptr;
}
else
{
void* tmp_buffer = buffer;
return reinterpret_cast<T*>(std::align(alignof(T), sizeof(T), tmp_buffer, size));
}
}
甚至
template <typename T>
T* get_object_from_buffer(std::uint8_t* buffer, std::size_t size)
{
// Caller shall check returned pointer against 'nullptr' to implement diagnostic reactions
return reinterpret_cast<T*>(
size == sizeof(T)
? std::align(alignof(T), sizeof(T), buffer, size)
: nullptr);
}