是什么static_assert做的,你会用它来做什么?(What does static_asse

2019-09-02 11:51发布

你能给其中一个例子static_assert(...) 'C++0x'将解决手头的问题优雅?

我熟悉运行时assert(...) 当我应该喜欢static_assert(...)在定期assert(...)

此外,在boost有个东西叫BOOST_STATIC_ASSERT ,是一样的static_assert(...)

Answer 1:

关闭我的头顶...

#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 :("


Answer 2:

静态断言是用来做在编译时断言。 当静态断言失败,程序根本不编译。 这是在不同情况下非常有用,如,例如,如果实现由代码一些功能,关键取决于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



Answer 3:

我用它来保证我对编译器的行为,标题,库,甚至我自己的代码的假设是正确的。 比如我在这里验证结构已被正确包装,以预期的大小。

struct LogicalBlockAddress
{
#pragma pack(push, 1)
    Uint32 logicalBlockNumber;
    Uint16 partitionReferenceNumber;
#pragma pack(pop)
};
BOOST_STATIC_ASSERT(sizeof(LogicalBlockAddress) == 6);

在一类包装stdio.hfseek()我已经采取了一些快捷方式enum Origin ,并检查这些快捷键与定义的常量对准stdio.h

uint64_t BasicFile::seek(int64_t offset, enum Origin origin)
{
    BOOST_STATIC_ASSERT(SEEK_SET == Origin::SET);

你应该更喜欢static_assertassert时的行为是在编译时定义,而不是在运行时,如我上面给出的例子。 一个例子不是这种情况下将包括参数和返回代码检查。

BOOST_STATIC_ASSERT是预先的C ++ 0x宏产生非法代码,如果条件不成立。 意图是一样的,尽管static_assert被标准化,可以提供更好的编译器诊断。



Answer 4:

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 ... */
};

这将导致一个编译时错误,如果上述任何条件未能得到满足。



Answer 5:

一个使用static_assert可能是确保结构(也就是与外界的接口,如网络或文件)正是您所期望的大小。 其中有人添加或修改从结构的成员没有意识到后果这会赶上的情况。 该static_assert会捡起来,并提醒用户。



Answer 6:

这并不直接回答了原来的问题,但让一个有趣的研究探讨如何执行这些编译之前,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");


Answer 7:

在不存在的概念之一可以使用static_assert为简单和可读编译时类型检查,例如,在模板:

template <class T>
void MyFunc(T value)
{
static_assert(std::is_base_of<MyBase, T>::value, 
              "T must be derived from MyBase");

// ...
}


文章来源: What does static_assert do, and what would you use it for?