你能给其中一个例子static_assert(...) 'C++0x'
将解决手头的问题优雅?
我熟悉运行时assert(...)
当我应该喜欢static_assert(...)
在定期assert(...)
此外,在boost
有个东西叫BOOST_STATIC_ASSERT
,是一样的static_assert(...)
你能给其中一个例子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
。
@Arak,响应您的评论:是的,你可以有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
的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
会捡起来,并提醒用户。
这并不直接回答了原来的问题,但让一个有趣的研究探讨如何执行这些编译之前,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");
在不存在的概念之一可以使用static_assert
为简单和可读编译时类型检查,例如,在模板:
template <class T>
void MyFunc(T value)
{
static_assert(std::is_base_of<MyBase, T>::value,
"T must be derived from MyBase");
// ...
}