我正在编写遗留API的 C ++ 包装器。这个API为我提供了一个指针值来保存额外的数据,我想用它实现小缓冲区优化。
我已经实现了is_small_pod
元函数,用于检查给定类型是否为 POD 并且它是否适合void*
:
template< typename Type >
struct is_small_pod
: std::integral_constant<
bool
, std::is_pod< Type >::type::value
&& sizeof( Type ) <= sizeof( void* )
>
{};
我正在设置这样的值:
// void*& param;
if( detail::is_small_pod< Type >() )
{
*static_cast< Type* >( ¶m ) = value;
} else {
param = new Type( value );
}
我是否正确实施此优化?我相信当值对齐与指针的对齐不兼容时,这将失败(奇数角情况可能如此)。这种情况是否可能,或者我只是过度思考它?我应该如何扩展元函数以检查兼容的对齐?
答案 0 :(得分:8)
类型的对齐方式不可能大于该类型的大小。
3.11对齐[basic.align]
[...] alignment 是一个实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。
5.3.3 Sizeof [expr.sizeof]
2 - [...] n 元素数组的大小 n 乘以元素的大小。
因此,您的代码只能在alignof(void *) < sizeof(void *)
时中断,而在大多数平台上都不是这样。
为安全起见,您可以写:
template< typename Type >
struct is_small_pod
: std::integral_constant<
bool
, std::is_pod< Type >::type::value
&& sizeof( Type ) <= sizeof( void* )
&& alignof( Type ) <= alignof( void* )
>
{};
答案 1 :(得分:0)
就像一般方法一样,你总是可以尝试测试你的理论。我想你会做这样的事情:
template< class Type >
bool TestAlignmentSanity( Type value )
{
// This function is only valid for small POD types
if( !detail::is_small_pod< Type >() )
return false;
// Temporary space covering alignments spanning the size of a void*
const int nBytes = sizeof(void*);
char buffer[sizeof(Type) + nBytes - 1];
// For each target alignment, test that a copy is successful.
for( int i = 0; i < nBytes; i++ )
{
Type * target = static_cast< Type* >( &buffer[i] );
// Sanity-check that the pointer was actually aligned as we requested
if( (char*)target != &buffer[i] ) return false;
// Copy and test that the result is as expected. Assumes '==' operator
// is defined... Otherwise, implement with byte comparisons.
*target = value;
if( !(*target == value) ) return false;
}
return true;
}
在这里,我测试了数据类型可以复制到任何跨越void*
大小的对齐方式。这只是一个想法。 =)