什么static_assert做的,你会怎么用它呢?
-
22-07-2019 - |
题
你能举个例子在哪里 static_assert(...) 'C++0x'
会解决的问题方面的优雅?
我所熟悉的运行时间 assert(...)
.当我应该喜欢 static_assert(...)
超过正常 assert(...)
?
此外,中 boost
也有一些是被称为 BOOST_STATIC_ASSERT
, 是它的一样 static_assert(...)
?
解决方案
关掉我的头顶...
#include "SomeLibrary.h"
static_assert(SomeLibrary::Version > 2,
"Old versions of SomeLibrary are missing the foo functionality. Cannot proceed!");
class UsingSomeLibrary {
// ...
};
假设 SomeLibrary::Version
被宣布为一个静态的常量,而不是被 #define
d(作为一个希望在C++图书馆)。
与具有实际汇编 SomeLibrary
和你的代码链接的一切,并执行可执行的只有 然后 为了找出你花了30分钟编制一个不兼容的版本 SomeLibrary
.
@阿拉克,响应你的评论:是的,你可以有 static_assert
只是坐出,无论,从查找:
class Foo
{
public:
static const int bar = 3;
};
static_assert(Foo::bar > 4, "Foo::bar is too small :(");
int main()
{
return Foo::bar;
}
$ g++ --std=c++0x a.cpp a.cpp:7: error: static assertion failed: "Foo::bar is too small :("
其他提示
静态的断言是用来做的断言,在编制时间。当静态的断言失败,程序简单地不编译。这是在不同的情况下非常有用,例如,如果实现某些功能通过代码,严重依赖于 unsigned int
目具有完全32位。你可以把一个静态的断言这样
static_assert(sizeof(unsigned int) * CHAR_BIT == 32);
在你的代码。在另一个平台,不同大小的 unsigned int
类型的汇编将会失败,因此提请注意的开发问题的部分代码并建议他们重新实现或重新检查它。
对于另一个例子,你可能希望通过一些整体价值 void *
指向一个函数(一个黑客,但是有用的,在时间),要确保整体的值,将适合的指针
int i;
static_assert(sizeof(void *) >= sizeof i);
foo((void *) i);
你可能需要的资产 char
类型的签名
static_assert(CHAR_MIN < 0);
或者那的整体司负值回合对零
static_assert(-5 / 2 == -2);
等等。
运行时断言,在许多情况下可以使用,而不是静态的断言,但是运行时断言,只有工作在运行时间和仅当控制转的断言。为此原因无法运行时的断言可以躺下休眠状态,未被发现针对长时间。
当然,表达静态的断言是一个编译的时间不变。它不能运行时间值。对于运行时值你有没有其他选择,只使用普通 assert
.
我用它来确保我的假设编译器的行为,标题,库,甚至我自己的代码是正确的。例如在这里,我证实,该结构已经被正确地包装的期望的大小。
struct LogicalBlockAddress
{
#pragma pack(push, 1)
Uint32 logicalBlockNumber;
Uint16 partitionReferenceNumber;
#pragma pack(pop)
};
BOOST_STATIC_ASSERT(sizeof(LogicalBlockAddress) == 6);
在一类包装 stdio.h
's fseek()
, 我已经采取了一些快捷方式 enum Origin
并检查那些快捷方式与常数定义通过 stdio.h
uint64_t BasicFile::seek(int64_t offset, enum Origin origin)
{
BOOST_STATIC_ASSERT(SEEK_SET == Origin::SET);
你应该喜欢 static_assert
在 assert
当行为的定义是在编制时间,而不是在运行时,这种作为例子,我给上。一个例子,在那里这是 不 这种情况下将包括的参数和返回代码检查。
BOOST_STATIC_ASSERT
是一个预C++0x宏产生的非法代码如果情况不满意。意图是相同的,尽管是 static_assert
是标准化和可以提供更好的编译器诊断。
BOOST_STATIC_ASSERT
是一个交叉平台包装 static_assert
功能。
目前,我使用static_assert为了执行"的概念"上的一类。
例如:
template <typename T, typename U>
struct Type
{
BOOST_STATIC_ASSERT(boost::is_base_of<T, Interface>::value);
BOOST_STATIC_ASSERT(std::numeric_limits<U>::is_integer);
/* ... more code ... */
};
这将造成编制的时间错误,如果上述任何条件得不到满足。
一个使用的 static_assert
可能是确保这一结构(这是一个界面与外部世界,诸如网络或文件)正是大小的期望。这将抓住的情况下,有人添加或修改的成员结构没有意识到的后果。的 static_assert
会把它捡起来,并提醒用户。
在缺乏概念的一个可以使用 static_assert
为简单的和可读的编写时间类型的检查,例如,在模板:
template <class T>
void MyFunc(T value)
{
static_assert(std::is_base_of<MyBase, T>::value,
"T must be derived from MyBase");
// ...
}
这并不直接回答问题的答案,但让一个有趣的研究成如何执行这些汇编的时间检查之前至C++11.
第2章(第2.1条)的 现代C++的设计 安德烈*Alexanderscu实现这一想法的编纂时的断言这样
template<int> struct CompileTimeError;
template<> struct CompileTimeError<true> {};
#define STATIC_CHECK(expr, msg) \
{ CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
比较的宏STATIC_CHECK()和static_assert()
STATIC_CHECK(0, COMPILATION_FAILED);
static_assert(0, "compilation failed");