如何让我的C ++编译器发出constexpr值(例如警告?)

时间:2017-12-19 18:38:16

标签: c++ compiler-warnings constexpr

(这有点像XY problem,但请耐心等待。)

我收到关于班次数量过大的编译警告。现在,为了诊断这一点,我希望我的编译器以某种方式发出constexpr值,该值用作移位量。

到目前为止,我已经完成它的方法是尝试实例化一个带有数字参数的类型,我知道我可以将其放在范围之外,然后添加我想要的constexpr值并得到一个错误,它显示了总和。但这是一个丑陋的黑客。有没有办法让constexpr值(希望不仅仅是整数)发送到标准错误流?例如连同一些解释性文字或警告信息?

我在询问GCC 6.x及更高版本和clang 4.x及更高版本。

3 个答案:

答案 0 :(得分:1)

嗯,显而易见的方法类似于你所说的 - 让编译器在发出诊断时提到值。

constexpr int I = 8 % 3;

template<int i>
class TheValueYouWantIs { static_assert(i != i); };


int main() {
    TheValueYouWantIs<I>();
}

因此:

prog.cpp: In instantiation of ‘class TheValueYouWantIs<2>’:
prog.cpp:8:27:   required from here
[...less informative stuff...]

警告显然更依赖于编译器,但应该很容易实现。但是,这类事情对char数组没有帮助。不是一个完整的解决方案。

答案 1 :(得分:1)

GCC在常量表达式中发出溢出错误消息时显示<<的操作数。当结果不用作常量表达式时,它仅在发出警告消息时不显示<<个操作数。你可以通过添加一个无意义的常量来利用它。

template <int> constexpr int f() { return 1; }
template <int> constexpr int g() { return 40; }
template <int I> constexpr int h() { return f<I>() << g<I>(); }
int main() { h<1234>(); }

这会导致出现警告而不提供有关问题值的信息:warning: left shift count >= width of type [-Wshift-count-overflow]

template <int> constexpr int f() { return 1; }
template <int> constexpr int g() { return 40; }
template <int I> constexpr int h() { constexpr int i = f<I>() << g<I>(); return f<I>() << g<I>(); }
int main() { h<1234>(); }

这会导致错误,其中包含有关问题值的信息(以及更多警告):error: right operand of shift expression ‘(1 << 40)’ is >= than the precision of the left operand

如果只有第二个操作数是一个常量表达式,它仍然没问题,对于这个特殊的警告,将左操作数变为常量1就足够了。

答案 2 :(得分:0)

这是非常丑陋的,但是以可辨别的,虽然可怕的格式生成表达式的名称及其值:

constexpr int I = 8 % 3;

#define CONCATENATE( s1, s2 )               s1 ## s2
#define EXPAND_THEN_CONCATENATE( s1, s2 )   CONCATENATE( s1, s2 )

template<int i>
class The_expression_named_in_the_previous_error_has_value{ static_assert(i != i, ""); };


#define ERROR_PRINT(_expr) \
EXPAND_THEN_CONCATENATE(In_the_next_error_you_will_find_the_value_of_the_expression__, _expr); \
The_expression_named_in_the_previous_error_has_value<I>();

int main() {
    ERROR_PRINT(I);
}

这产生(使用GCC 6):

main.cpp: In function ‘int main()’:
main.cpp:11:25: error: ‘In_the_next_error_you_will_find_the_value_of_the_expression__I’ was not declared in this scope
 EXPAND_THEN_CONCATENATE(In_the_next_error_you_will_find_the_value_of_the_expression__, _expr); \
                         ^
main.cpp:3:45: note: in definition of macro ‘CONCATENATE’
 #define CONCATENATE( s1, s2 )               s1 ## s2
                                             ^
main.cpp:11:1: note: in expansion of macro ‘EXPAND_THEN_CONCATENATE’
 EXPAND_THEN_CONCATENATE(In_the_next_error_you_will_find_the_value_of_the_expression__, _expr); \
 ^
main.cpp:15:5: note: in expansion of macro ‘ERROR_PRINT’
     ERROR_PRINT(I);
     ^
main.cpp: In instantiation of ‘class The_expression_named_in_the_previous_error_has_value<2>’:
main.cpp:15:5:   required from here
main.cpp:7:61: error: static assertion failed: 
 class The_expression_named_in_the_previous_error_has_value{ static_assert(i != i, ""); };

但是我确信通过一些constexpr-string-trickery可以大大改进。