C++ 对于相同的静态断言消息,我应该依赖宏吗?

C++ 对于相同的静态断言消息,我应该依赖宏吗?,c++,c++11,macros,string-literals,static-assert,C++,C++11,Macros,String Literals,Static Assert,具有以下语法,表示需要字符串文字 静态断言(bool_constexpr,字符串文本) 由于在编译时无法观察到字符串的实例,因此以下代码无效: const std::string ERROR_MESSAGE{"I assert that you CAN NOT do this."}; static_assert(/* boolean expression */ ,ERROR_MESSAGE); 我的代码中到处都是静态断言,它们都显示相同的错误消息。 既然需要字符串文字,那么最好用宏替换所有

具有以下语法,表示需要字符串文字

静态断言(bool_constexpr,字符串文本


由于在编译时无法观察到字符串的实例,因此以下代码无效:

const std::string ERROR_MESSAGE{"I assert that you CAN NOT do this."};
static_assert(/* boolean expression */ ,ERROR_MESSAGE);

我的代码中到处都是静态断言,它们都显示相同的错误消息。 既然需要字符串文字,那么最好用宏替换所有重复的字符串文字,还是有更好的方法

// Is this method ok? 
// Should I hand type them all instead?
// Is there a better way?

#define _ERROR_MESSAGE_ "danger"

static_assert(/* boolean expression 1*/ ,_ERROR_MESSAGE_);
//... code ...
static_assert(/* boolean expression 2*/ ,_ERROR_MESSAGE_);
//... code ...
static_assert(/* boolean expression 3*/ ,_ERROR_MESSAGE_);
在C++中,不应该将常量定义为宏。将其定义为常量。这就是常数的用途

此外,以下划线开头,后跟大写字母的名称(如
\u错误\u消息
)将保留给实现

这就是说,,使用宏进行静态断言是个好主意,既可以确保正确的字符串参数,也可以支持可能没有
静态断言
的编译器,但该宏不是C风格的常量:它将表达式作为参数,并将该表达式作为字符串消息提供

这是我当前的

#pragma一次
//版权所有(c)2013阿尔夫·P·斯坦巴赫
//“…”参数允许使用“”进行模板实例化。
#定义CPPX\u静态\u断言\u执行(消息\u文字,…)\
静态断言(uuu VA_uargs_uuuuuuuuuuuuuuuuuuuuuuuuuuuuu,“CPPX_u静态断言:”消息文字)
#定义CPPX_静态_断言(…)\
CPPX_STATIC_ASSERT___IMPL(#__VA_ARGS__,__VA_ARGS__)
//对于std::integral_常量之类的参数
#定义CPPX\u静态\u断言\u是(…)\
CPPX_STATIC_ASSERT___IMPL(#__VA_ARGS__,__VA_ARGS_::value)

正如您所看到的,即使编译器确实有
静态断言

,也会涉及到一些微妙之处,因为断言将在编译时得到解决,所以我看不到使用“pretty”错误消息的直接好处。如果断言失败,您知道失败点。@pauluss86是的,但是如果布尔表达式很复杂,理解它失败的原因可能会很困难。这是事实,尽管我总是试图在断言中避免复杂的条件。通常它只是一个“x&&y”或“x | | y”。我添加的错误消息也很短;我不喜欢多行表达和坚持我认为你没有抓住要点。他们问是否可以用宏替换文字。@jrok宏有很多潜在的危险,因此我想检查它是否是代码维护的最佳方法。@jrok:如果不澄清其含义,就无法合理地回答关于“ok”(您的问题)或“best”(OP的文字问题)。否则一切都是主观的,有着不同的善良标准。但是,将OP将文字字符串定义为宏的想法与这个答案将整个调用定义为宏的想法相比较,您可以看到,后者使得编写每个需要静态断言的地方的工作量大大减少。G虽然你的方法会奏效,但OP不会或会有一两个怪癖。例如。某些版本中的Microsoft预处理器不会传输unicode编码的消息。
#pragma once
// Copyright (c) 2013 Alf P. Steinbach

// The "..." arguments permit template instantiations with "<" and ">".

#define CPPX_STATIC_ASSERT__IMPL( message_literal, ... ) \
    static_assert( __VA_ARGS__, "CPPX_STATIC_ASSERT: " message_literal  )

#define CPPX_STATIC_ASSERT( ... ) \
    CPPX_STATIC_ASSERT__IMPL( #__VA_ARGS__, __VA_ARGS__ )

// For arguments like std::integral_constant
#define CPPX_STATIC_ASSERT_YES( ... ) \
    CPPX_STATIC_ASSERT__IMPL( #__VA_ARGS__, __VA_ARGS__::value )