对于对象大小的`static_assert`更好的消息

yzt*_*yzt 3 c++ static-assert c-preprocessor c++11

我一直在使用static_assert(以及标准化之前的变体).我相信我们很多人都会使用它的一个用途是确保敏感数据结构的大小保持在平台和配置之间.例如:

class SizeSensitiveClass
{
    // ...
};

static_assert (sizeof(SizeSensitiveClass) == 18, "Check the size!");
Run Code Online (Sandbox Code Playgroud)

现在,我已经编写了一个方便的宏来帮助这个特殊用途:

#define STATIC_ASSERT_SIZE(T, sz)  (sizeof(T) == (sz), "Size of '" #T "' doesn't match the expected value.")
Run Code Online (Sandbox Code Playgroud)

像这样使用:

STATIC_ASSERT_SIZE (SizeSensitiveClass, 18);
Run Code Online (Sandbox Code Playgroud)

产生此输出:(在编译时,显然,以编译错误的形式)

'SizeSensitiveClass'的大小与预期值不匹配.

这很好,但我想知道是否可以扩展此宏的实现(保持接口完整)以输出当前大小和数据结构的预期大小.理想情况下,输出应该类似于:

'SizeSensitiveClass'的大小与预期值不匹配(20对18).

即使是目前的尺寸也会非常方便.这可能吗?

我正在使用VC12(Visual C++ 2013)和GCC 4.8.1.我很感激任何可以移植到至少这两个的解决方案/技术/方法.

我应该提到我已经尝试过常见的"stringize"技巧,但它不起作用(正如人们所预料的那样.)它只是sizeof(T)在输出中生成文字字符串.

我有一个模糊的概念,这可能是使用constexprs(生成消息字符串)实现的,但我不熟悉它们.

Dan*_*rey 6

这可能不是您设想的解决方案,但它会生成一条错误消息,该消息始终包含实际大小和预期大小,从而关闭错误消息static_assert:

#include <type_traits>

template< typename Type, std::size_t ExpectedSize, std::size_t ActualSize = 0 >
struct validate_size : std::true_type
{
    static_assert( ActualSize == ExpectedSize,
                   "actual size does not match expected size" );
};

template< typename Type, std::size_t ExpectedSize >
struct validate_size< Type, ExpectedSize, 0 >
  : validate_size< Type, ExpectedSize, sizeof( Type ) >
{};

int main()
{
    static_assert( validate_size< int, 4 >::value, "Oops" );
    static_assert( validate_size< int, 5 >::value, "Oops2" );
}
Run Code Online (Sandbox Code Playgroud)

来自GCC 4.8的错误消息:

main.cpp: In instantiation of 'struct validate_size<int, 5ul, 4ul>':
main.cpp:10:8:   required from 'struct validate_size<int, 5ul>'
main.cpp:15:43:   required from here
main.cpp:6:5: error: static assertion failed: actual size does not match expected size
     static_assert( ActualSize == ExpectedSize, "actual size does not match expected size" );
     ^
Run Code Online (Sandbox Code Playgroud)

来自Clang的消息还包含<int, 5ul, 4ul>-part,自己检查VS.

实例

更新:您显然可以保持您的界面完整:

#define STATIC_ASSERT_SIZE(T, sz) static_assert(validate_size<T,sz>::value, "")
Run Code Online (Sandbox Code Playgroud)