编译时的std :: cout等效,或者c ++ 11中编译时常量值的static_assert字符串化

时间:2012-11-20 01:34:13

标签: c++ c++11 cout constexpr static-assert

有没有办法在编译时打印constexpr#define d值的值?我希望等效于std::cout <<,或某种方式来做类似

的事情
constexpr int PI_INT = 4;
static_assert(PI_INT == 3,
              const_str_join("PI_INT must be 3, not ", const_int_to_str(PI_INT)));

编辑我可以使用constexpr进行一些基本的编译时打印,至少在gcc上做类似

的操作
template <int v>
struct display_non_zero_int_value;

template <>
struct display_non_zero_int_value<0> { static constexpr bool foo = true; };

static constexpr int v = 1;

static_assert(v == 0 && display_non_zero_int_value<v>::foo, "v == 0");

给了我error: incomplete type ‘display_non_zero_int_value<1>’ used in nested name specifier static_assert(v == 0 && display_non_zero_int_value<v>::foo, "v == 0");。 (另一方面,icpc不太有帮助,只是说error: incomplete type is not allowed)有没有办法编写一个可以概括它的宏,以便我可以做类似的事情

constexpr int PI_INT = 4;
PRINT_VALUE(PI_INT)

并收到涉及4的错误消息,不知何故?

1 个答案:

答案 0 :(得分:12)

引用§7/ 1 [dcl.dcl] 中声明的语法:

  

static_assert-declaration:

     

static_assert(constant-expression,string-literal);

标准说它必须是一个字符串文字,所以你运气不好;你不能使用constexpr函数来构造你的错误信息。

但是,您可以使用您喜欢的任何预处理器魔法来生成字符串文字。如果PI_INT是#define但不是constexpr int,您可以使用以下内容:

#define PI_INT 4
#define pi_err_str_(x) #x
#define pi_err_str(x) pi_err_str_(x)
#define pi_int_err "PI_INT must be 3, not " pi_err_str(PI_INT)

static_assert(PI_INT == 3, pi_int_err);

输出:

  

错误:静态断言失败:“PI_INT必须为3,而不是4”


修改以回应OP的评论和更新的问题

  

有没有办法编写一个可以概括它的宏,以便我可以做类似的事情......并获得一个涉及4的错误消息,不知何故?

当然,假设您很乐意依赖于编译器特定的错误消息行为,那么一些预处理器魔术可以概括为:

#define strcat_(x, y) x ## y
#define strcat(x, y) strcat_(x, y)
#define PRINT_VALUE(x) template <int> struct strcat(strcat(value_of_, x), _is); static_assert(strcat(strcat(value_of_, x), _is)<x>::x, "");

constexpr int PI_INT = 4;
PRINT_VALUE(PI_INT)
  

stackoverflow / 13465334.cpp:20:1:错误:不完整类型'value_of_PI_INT_is&lt; 4&gt;'用于嵌套名称说明符

至于其他编译器,我不知道你可以随意做什么,但是你可能想看看boost的static_assert.hpp的副本,看看那里使用的任何技巧是否可以用来获得一个评估的模板arg印刷。