Ara*_*raK 110 c++ debugging assert static-assert c++11
你能举个例子static_assert(...)来优雅地解决问题吗?
我熟悉运行时assert(...).我什么时候应该static_assert(...)比常规更喜欢assert(...)?
此外,boost有一个叫做的东西BOOST_STATIC_ASSERT,它是一样的static_assert(...)吗?
AnT*_*AnT 125
静态断言用于在编译时进行断言.当静态断言失败时,程序根本无法编译.这在不同情况下很有用,例如,如果您通过严格依赖于unsigned int具有正好32位的对象的代码实现某些功能.你可以像这样放一个静态断言
static_assert(sizeof(unsigned int) * CHAR_BIT == 32);
Run Code Online (Sandbox Code Playgroud)
在你的代码中.在另一个平台上,使用不同大小的unsigned int类型,编译将失败,从而引起开发人员对代码中有问题部分的注意,并建议他们重新实现或重新检查它.
再举一个例子,您可能希望将一些整数值作为void *指向函数的指针传递(一个hack,但有时很有用),并且您希望确保整数值适合指针
int i;
static_assert(sizeof(void *) >= sizeof i);
foo((void *) i);
Run Code Online (Sandbox Code Playgroud)
您可能希望资产char类型已签名
static_assert(CHAR_MIN < 0);
Run Code Online (Sandbox Code Playgroud)
或者负值的积分除以零
static_assert(-5 / 2 == -2);
Run Code Online (Sandbox Code Playgroud)
等等.
在许多情况下可以使用运行时断言而不是静态断言,但运行时断言仅在运行时才起作用,并且仅在控制通过断言时才起作用.由于这个原因,失败的运行时断言可能处于休眠状态,长时间未检测到.
当然,静态断言中的表达式必须是编译时常量.它不能是运行时值.对于运行时值,您没有其他选择,只能使用普通值assert.
Mar*_*off 76
脱离我的头顶......
#include "SomeLibrary.h"
static_assert(SomeLibrary::Version > 2,
"Old versions of SomeLibrary are missing the foo functionality. Cannot proceed!");
class UsingSomeLibrary {
// ...
};
Run Code Online (Sandbox Code Playgroud)
假设它SomeLibrary::Version被声明为静态const,而不是#defined(正如人们在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;
}
Run Code Online (Sandbox Code Playgroud)
$ g++ --std=c++0x a.cpp
a.cpp:7: error: static assertion failed: "Foo::bar is too small :("
Mat*_*ner 12
我用它来确保我对编译器行为,头文件,库甚至我自己的代码的假设是正确的.例如,我在此验证结构已正确打包到预期大小.
struct LogicalBlockAddress
{
#pragma pack(push, 1)
Uint32 logicalBlockNumber;
Uint16 partitionReferenceNumber;
#pragma pack(pop)
};
BOOST_STATIC_ASSERT(sizeof(LogicalBlockAddress) == 6);
Run Code Online (Sandbox Code Playgroud)
在一类包装stdio.h的fseek(),我已经采取了一些快捷方式enum Origin,并检查这些快捷键与定义的常量对齐stdio.h
uint64_t BasicFile::seek(int64_t offset, enum Origin origin)
{
BOOST_STATIC_ASSERT(SEEK_SET == Origin::SET);
Run Code Online (Sandbox Code Playgroud)
你应该更喜欢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 ... */
};
Run Code Online (Sandbox Code Playgroud)
如果不满足上述任何条件,这将导致编译时错误.
的一种用法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");
// ...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
54869 次 |
| 最近记录: |