标签: static-assert

是否允许编译器评估静态断言中的重言式

提供static_assert模板通常很有帮助.在模板不应该以某种方式实例化的情况下,我经常这样做

template<typename T, typename = void>
struct S
{
    static_assert(false, "Unconditional error");
    static_assert(sizeof(T) != sizeof(T), "Error on instantiation");
};

template<typename T>
struct S<T, std::enable_if_t<std::is_integral_v<T>>>
{
    // ...
};
Run Code Online (Sandbox Code Playgroud)

static_assert即使没有实例化,第一个将立即失败S,而如果没有实例化将导致主模板,第二个将成功.

第二个static_assert显然是一个重言式,但它"取决于" T,以达到预期的效果.但这有保证吗?是否允许编译器评估这些重言式?

c++ static-assert language-lawyer

9
推荐指数
1
解决办法
200
查看次数

为什么更喜欢基于typedef的静态断言的基于模板的静态断言?

对于没有内置的C++版本,有两种广泛使用的静态断言实现static_assert.

第一个用于Boost并使用模板和该模板的特化:

template <bool> struct static_assert;
template <> struct static_assert<true> {}; // only true is defined
#define  STATIC_ASSERT(x) static_assert<(x)>()
Run Code Online (Sandbox Code Playgroud)

这里一旦检查的条件为false,编译器就无法找到模板的通用版本,编译失败.

第二个使用typedef:

#define STATIC_ASSERT( x ) typedef char __STATIC_ASSERT__[( x )?1:-1]
Run Code Online (Sandbox Code Playgroud)

这里一旦违反了检查条件,编译器就会尝试typedef一个大小为-1的数组,这是非法的,因此是编译时错误.

对我来说后者更好,因为它保证不发出代码,也可以像这样使用(从这里):

template<int Shift> class BinaryFlag {
    STATIC_ASSERT( 0 <= Shift && Shift < sizeof( DWORD) * CHAR_BIT );
    public:
    static const DWORD FlagValue = static_cast<DWORD>( 1 << Shift );
};
#define BINARY_FLAG( n ) CBinaryFlag<n>::FlagValue
Run Code Online (Sandbox Code Playgroud)

而前者不能那样使用.

有没有理由更喜欢静态断言的前一个实现而不是后者?

c++ templates static-assert visual-c++

8
推荐指数
1
解决办法
4364
查看次数

用于检测模板特化的模板元函数

这个问题的启发,我想知道是否有一些编译时检查可以引入检测两个给定的模板实例:

template <typename T>
class Templ...

typedef Templ<std::string> stringInstance;
typedef Templ<double> doubleInstance;
Run Code Online (Sandbox Code Playgroud)

是从相同的定义构造的,或者如果它们是从Templ模板的不同特化构建的

所以基本上假设的模板函数将表现如下:

template <typename T>
class Templ
{}

template <>
class Templ<std::string>
{}

template <>
class Templ<double>
{}

template <typename T1,typename T2>
class Belong_To_Same_Templ_Definition
{}

//tests
typedef Templ<std::string> stringInstance;
typedef Templ<double> doubleInstance;
typedef Templ<int> intInstance;
typedef Templ<char> charInstance;

assert( Belong_To_Same_Templ_Definition< intInstance , charInstance >::value == true);
assert( Belong_To_Same_Templ_Definition< intInstance , doubleInstance >::value == false);
assert( Belong_To_Same_Templ_Definition< stringInstance , doubleInstance >::value == false);
Run Code Online (Sandbox Code Playgroud)

有可能创造这种元功能吗?

c++ static-assert compile-time template-specialization template-meta-programming

8
推荐指数
1
解决办法
188
查看次数

MSVC12认为从std :: array派生的聚合不是pod

鉴于以下内容

#include <array>

struct litmus final : std::array<unsigned char, 16>
{
};

static_assert(std::is_pod<std::array<unsigned char, 16> >::value, "not pod");

// this fails on MSVC:
static_assert(std::is_pod<litmus>::value, "not pod");
Run Code Online (Sandbox Code Playgroud)

以下编译器同意litmuspod:

但是,MSVC12(VS2013 RTM)认为第二个断言失败.

  1. 谁是对的?
  2. 是否有任何技巧可以让MSVC将该类视为pod?

编辑有关信息:is_trivially_copyable<litmus>在MSVC上返回true-ness.对于许多不严格要求实际POD的情况,这可能很有用.

c++ static-assert pod visual-c++

8
推荐指数
1
解决办法
292
查看次数

为什么一个表达式不变,而另一个表达式不变?

为什么Visual Studio 2013编译器拒绝第一个静态断言(错误C2057),而不是第二个?

#include <limits>

typedef int Frequency;

const Frequency minHz{ 0 };
const Frequency maxHz{ std::numeric_limits<Frequency>::max() };
const Frequency invalidHz{ -1 };
static_assert(minHz < maxHz, "minHz must be less than maxHz");                // C2057
static_assert(invalidHz < minHz || invalidHz > maxHz, "invalidHz is valid");  // OK
Run Code Online (Sandbox Code Playgroud)

c++ static-assert c++11 visual-studio-2013

8
推荐指数
1
解决办法
148
查看次数

如果 constexpr 没有被丢弃,Static_assert 在里面

static_assert在 的 false 分支中应丢弃以下内容if constexpr,但由于断言失败而导致编译失败:

#include <type_traits>                                                                                                                                                                              

template <class T>                                                                                                                                                                                  
constexpr bool f() {                                                                                                                                                                                
  if constexpr (std::is_same<T, int>::value) return true;                                                                                                                                                                                                                                                                    
  else static_assert(false, "message");                                                                                                                                                             
}                                                                                                                                                                                                   

int main () {                                                                                                                                                                                       
  if constexpr (f<int>()) return 1;                                                                                                                                                                 
  return 0;                                                                                                                                                                                         
} 
Run Code Online (Sandbox Code Playgroud)

我希望丢弃的分支if constexpr不会被评估,因为它f是用 type 实例化的int

用 Gcc 7.2 (-std=c++17) 编译

c++ instantiation static-assert constexpr if-constexpr

8
推荐指数
0
解决办法
1868
查看次数

是否可以为不应编译的表达式表达static_assert?

我想用以下形式表达一个static_assert:

static_assert(expression should not compile);
Run Code Online (Sandbox Code Playgroud)

让我添加一个完整的示例:

template <bool Big>
struct A{};

template <>
struct A<true>
{
    void a() {}
};

A<false> b;

static_assert(!compile(b.a()));
or
static_assert(!compile(A<false>::a()));
Run Code Online (Sandbox Code Playgroud)

因此,该想法是要确保不会编译表达式(具有有效语法)。

如果可能的话,该解决方案仅使用C ++ 11会更好。

c++ static-assert c++11

8
推荐指数
1
解决办法
213
查看次数

是否可以在 GCC/GNU C 中编写一个 _Static_assert 来验证编译时内存中位字段的布局?

假设我有以下定义:

#include <stdbool.h>
#include <stdint.h>
#define ASSERT(cond) _Static_assert(cond, #cond)

typedef union {
    struct {
        bool bit0:1;
        bool bit1:1;
        bool bit2:1;
        bool bit3:1;
        bool bit4:1;
        bool bit5:1;
        bool bit6:1;
        bool bit7:1;
    };
    uint8_t bits;
} byte;

ASSERT(sizeof(byte) == sizeof(uint8_t));
Run Code Online (Sandbox Code Playgroud)

能不能写个代码,比如

#include <assert.h>
// ...
    assert(((byte) { .bit0 = 1 }).bits == 0b00000001);
    assert(((byte) { .bit1 = 1 }).bits == 0b00000010);
    assert(((byte) { .bit2 = 1 }).bits == 0b00000100);
    assert(((byte) { .bit3 = 1 }).bits == 0b00001000);
    assert(((byte) { .bit4 = 1 …
Run Code Online (Sandbox Code Playgroud)

c gcc static-assert assertion bit-fields

8
推荐指数
1
解决办法
291
查看次数

如果定义了枚举常量,如何静态断言?

我有这个 C++14 代码:

#include <type_traits>

struct f1 {
    enum struct e { a };
};

struct f2 {
    enum struct e {};
};

template <typename T>
struct my_struct {
    using e = typename T::e;
    my_struct()
    : _e{e::a} {} // e::a used here
    e _e;
};

int main() {
    my_struct<f1> a;
    my_struct<f2> b; // compilation fails
}
Run Code Online (Sandbox Code Playgroud)

显然,编译失败,类似于'a' is not a member of 'my_struct<f2>::e'. 我真的很想向 中添加一些静态断言my_struct,以添加自定义错误消息。首先,我可以检查是否e实际上是一个枚举:

static_assert(std::is_enum<e>::value, "my message");
Run Code Online (Sandbox Code Playgroud)

那么,我应该添加什么来静态断言e::a定义的?

c++ static-assert c++14

8
推荐指数
1
解决办法
108
查看次数

在 C++ 中静态区分枚举和枚举类?

我有一个事件处理程序类,它使用模板参数来设置事件类型。我想将这些事件类型强制为一字节大小的枚举类。针对大小的静态断言不是问题,但我无法在网上找到有关如何静态区分enumenum class 的信息

我现在的解决方案是使用C++ 前端实现语法扩展来断言枚举,然后断言正确的大小。在大多数平台上这是有效的,因为枚举使用int类型(通常大于一个字节)。

但这会导致稍微误导性的错误消息。我喜欢彻底。

我可以做哪些检查来传递类枚举,但会因常规的旧枚举而失败?


我不能使用type_traits,因为我使用的编译器(avr-gcc)不支持它。然而type_traits,当需要增加时,我会不断实施我自己的。因此,有关解决方案的任何提示type_traits仍然有用!


最小的例子:

// Event types
enum class tPass     : uint8_t  {}; 
enum class tFailSize : uint16_t {}; // Fail on size!
enum       tFailType            {}; // Currently fails on size, would like to fail on type!

// Event handler
template <typename TEvent>
class tEventHandler 
{
    static_assert(__is_enum(TEvent),   "Must be class enum!"); // Doesn't really check for CLASS …
Run Code Online (Sandbox Code Playgroud)

c++ enums enumeration static-assert enum-class

8
推荐指数
1
解决办法
201
查看次数