在static_assert()中在编译时显示整数

b3n*_*nj1 11 c++ macros integer static-assert c++11

这是我正在尝试做的简化版本

enum First
{
    a,
    b,
    c,
    nbElementFirstEnum,
};
enum Second
{
    a,
    b,
    c,
    nbElementSecondEnum,
};

static_assert(
    First::nbElementFirstEnum == Second::nbElementSecondEnum,
    "Not the same number of element in the enums.");
/*static_assert(  
    First::nbElementFirstEnum == Second::nbElementSecondEnum, 
    "Not the same number of element in the enums." + First::nbElementFirstEnum + " " + Second::nbElementSecondEnum);*/
Run Code Online (Sandbox Code Playgroud)

但是我希望能够在断言消息中打印First :: nbElementFirstEnum和Second :: nbElementSecondEnum的值(就像在注释版本中显然不起作用).我尝试使用"#"进行宏连接.我还尝试使用可变参数模板,使用%10检索每个数字并将"0"字符添加到检索到的值,但我得到的只是constexpr char [].

所以我的问题是如何让我的枚举值以字符串文字打印.

可能重复:

C++ 11 static_assert:参数化错误消息

在static_assert输出中集成类型名称?

最有趣的话题是: 在编译时打印sizeof(T) 但是我不希望有警告或退出代码来知道值.

Use*_*ess 5

基本上可以正常工作,尽管可以稍作努力(通过使V1和V2的总和为256的倍数)来断开。因此,我认为您的解决方案比较丑陋,但功能更强大。

template <int V1, int V2> struct AssertEquality
{
    static const char not_equal_warning = V1 + V2 + 256;
};

template <int V> struct AssertEquality<V, V>
{
    static const bool not_equal_warning = 0;
};

#define ASSERT_EQUALITY(V1, V2) static_assert( \
    AssertEquality<static_cast<int>(V1), \
                   static_cast<int>(V2)>::not_equal_warning == 0, \
    #V1 " != " #V2 );

// ...

ASSERT_EQUALITY(First::nbElementFirstEnum, Second::nbElementSecondEnum);
Run Code Online (Sandbox Code Playgroud)

输出看起来像:

g++ -std=c++0x -c chksz.cpp
chksz.cpp: In instantiation of ‘const char AssertEquality<3, 2>::not_equal_warning’:
chksz.cpp:40:124:   instantiated from here
chksz.cpp:5:53: warning: overflow in implicit constant conversion
chksz.cpp:40:1: error: static assertion failed: "First::nbElementFirstEnum != Second::nbElementSecondEnum"
Run Code Online (Sandbox Code Playgroud)

作为参考,static_assert即使布尔条件根本不编译,此原始版本也取决于gcc打印消息。

template <typename Enum1, int Max1, typename Enum2, int Max2>
struct AssertSameSizeEnums;

template <typename Enum1, int EnumMax, typename Enum2>
struct AssertSameSizeEnums<Enum1, EnumMax, Enum2, EnumMax> {};
// only define the special case where Max1 and Max2 have the same integer value

#define ASSERT_SAME_SIZE_ENUMS(E1, M1, E2, M2) static_assert( \
    sizeof(AssertSameSizeEnums<E1, E1::M1, E2, E2::M2>), \
    #E1 "::" #M1 " != " #E2 "::" #M2 );

enum class First {
    a, b, c, nbElementFirstEnum,
};
enum class Second {
    a, b, c, nbElementSecondEnum,
};

ASSERT_SAME_SIZE_ENUMS(First, nbElementFirstEnum, Second, nbElementSecondEnum);
Run Code Online (Sandbox Code Playgroud)

注意,我将您的枚举更改为强类型,因为否则枚举的常量名称发生冲突。如果您具有弱类型的枚举,则应将FirstSecond传递给宏,以命名封闭范围。

现在,如果我注释掉其中一个值(因此枚举大小不同),则会得到:

g++ -std=c++0x -c chksz.cpp
chksz.cpp:25:113: error: invalid application of ‘sizeof’ to incomplete type ‘AssertSameSizeEnums<First, 3, Second, 2>’
chksz.cpp:25:1: error: static assertion failed: "First::nbElementFirstEnum != Second::nbElementSecondEnum"
Run Code Online (Sandbox Code Playgroud)

看到整数值在不完整类型错误中如何显示,以及符号名称在静态断言中如何显示?


b3n*_*nj1 5

这是我找到的解决方案,我们收到一条带有值的警告消息和 static_assert 错误消息。

template<int N>
struct TriggerOverflowWarning
{
    static constexpr char value() { return N + 256; }
};

template <int N, int M, typename Enable = void>
struct CheckEqualityWithWarning
{
    static constexpr bool value = true;
};

template <int N, int M>
struct CheckEqualityWithWarning<N, M, typename std::enable_if<N != M>::type>
{
    static constexpr bool value = (TriggerOverflowWarning<N>::value() == TriggerOverflowWarning<M>::value());
};

static constexpr int a = 9;
static constexpr int b = 10;

static_assert(CheckEqualityWithWarning<a, b>::value, "Mismatch.");
Run Code Online (Sandbox Code Playgroud)

这是海湾合作委员会的输出:

g++ -std=c++11 -c test.cpp
test.cpp: In instantiation of 'static constexpr char TriggerOverflowWarning<N>::value() [with int N = 10]':
test.cpp:18:112:   required from 'constexpr const bool CheckEqualityWithWarning<9, 10>::value'
test.cpp:24:51:   required from here
test.cpp:6:52: warning: overflow in implicit constant conversion [-Woverflow]
test.cpp: In instantiation of 'static constexpr char TriggerOverflowWarning<N>::value() [with int N = 9]':
test.cpp:18:112:   required from 'constexpr const bool CheckEqualityWithWarning<9, 10>::value'
test.cpp:24:51:   required from here
test.cpp:6:52: warning: overflow in implicit constant conversion [-Woverflow]
test.cpp:24:5: error: static assertion failed: Mismatch.
Run Code Online (Sandbox Code Playgroud)

它基于此解决方案:在编译时打印 sizeof(T)


Ser*_*tch 5

首先是一个帮助类,用于在编译器输出中打印模板参数值:

template<size_t A, size_t B> struct TAssertEquality {
  static_assert(A==B, "Not equal");
  static constexpr bool _cResult = (A==B);
};
Run Code Online (Sandbox Code Playgroud)

然后你需要在哪里测试它:

static constexpr bool _cIsEqual = 
  TAssertEquality<First::nbElementFirstEnum, Second::nbElementSecondEnum>::_cResult;
Run Code Online (Sandbox Code Playgroud)

编译器错误消息如下所示:

注意:请参阅正在编译的类模板实例化 'TAssertEquality<32,64>' 的参考