C++ 如何制作我的C++;编译器发出一个constexpr值(例如,在警告中?)
(这有点像是个玩笑,但请耐心听我说。) 我收到了一条关于班次太多的警告。现在,为了诊断这个问题,我希望我的编译器以某种方式发出C++ 如何制作我的C++;编译器发出一个constexpr值(例如,在警告中?),c++,compiler-warnings,constexpr,C++,Compiler Warnings,Constexpr,(这有点像是个玩笑,但请耐心听我说。) 我收到了一条关于班次太多的警告。现在,为了诊断这个问题,我希望我的编译器以某种方式发出constexpr值,该值用作移位量 到目前为止,我所做的是尝试用一个数字参数实例化一个类型,我知道我可以将其放置在范围之外,然后添加我想要的constexpr值,得到一个显示总和的错误。但这是一个丑陋的黑客。有没有一种方法可以将constexpr值(希望不仅仅是整数)发送到标准错误流?e、 g.连同一些解释性文字或警告信息 我问的是GCC 6.x及更高版本和clang
constexpr
值,该值用作移位量
到目前为止,我所做的是尝试用一个数字参数实例化一个类型,我知道我可以将其放置在范围之外,然后添加我想要的constexpr值,得到一个显示总和的错误。但这是一个丑陋的黑客。有没有一种方法可以将constexpr值(希望不仅仅是整数)发送到标准错误流?e、 g.连同一些解释性文字或警告信息
我问的是GCC 6.x及更高版本和clang 4.x及更高版本。好吧,显而易见的方法与您所说的类似——让编译器在发出诊断时提及该值
constexpr int I = 8 % 3;
template<int i>
class TheValueYouWantIs { static_assert(i != i); };
int main() {
TheValueYouWantIs<I>();
}
constexpr int I=8%3;
模板
将您想要的值分类为{static_assert(i!=i);};
int main(){
Youwantis()的值;
}
因此:
prog.cpp:class TheValueYouWantIs'实例化中:
进度cpp:8:27:从这里开始需要
[…信息量较少的东西…]
警告显然更依赖于编译器,但应该很容易实现。不过,这种方法对字符数组没有帮助。这不是一个完整的解决方案。这非常难看,但会以一种可识别但糟糕的格式生成表达式的名称及其值:
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);
}
constexpr int I=8%3;
#定义连接(s1,s2)s1##s2
#定义扩展然后连接(s1,s2)连接(s1,s2)
模板
在_previous _error _具有{static _assert(i!=i,“”);}值的_中,对名为_的_表达式_进行初始化;
#定义错误\u打印(\u expr)\
展开然后连接(在下一个错误中找到表达式的值)\
_previous_error_中名为_的_表达式_具有_value();
int main(){
打印错误(I);
}
这将产生(使用GCC 6):
main.cpp:在函数“int main()”中:
main.cpp:11:25:error:'In_the_next_error_you_will_find_该表达式的_值_未在此范围内声明
展开然后连接(在下一个错误中找到表达式的值)\
^
main.cpp:3:45:注:在宏“连接”的定义中
#定义连接(s1,s2)s1##s2
^
main.cpp:11:1:注意:在宏的展开中“展开然后连接”
展开然后连接(在下一个错误中找到表达式的值)\
^
main.cpp:15:5:注意:在宏“ERROR\u PRINT”的展开中
打印错误(I);
^
main.cpp:在实例化“类中的\u表达式\u在\u中命名的\u之前的\u错误\u具有\u值”时:
main.cpp:15:5:从这里开始需要
main.cpp:7:61:错误:静态断言失败:
在_previous _error _具有{static _assert(i!=i,“”);}值的_中,对名为_的_表达式_进行初始化;
但是我相信这可以通过一些constexpr字符串技巧得到极大的改进。GCC displays
你能告诉我们你认为什么是丑陋的黑客吗?@路人:这基本上是斯奈夫特尔写的。@hvd:思考模板。静态断言(I!=I)
格式不正确,应该用类似于静态断言的东西来代替(始终为假::值)
@Jarod42足够公平。不过,我不知道有哪位编译器在第一阶段会不厌其烦地抱怨这个问题。@Pezo-不,问题是编译器不必实例化模板来抱怨。这使得练习毫无意义。@Pezo Jarod的观点是,即使在看到tem之前,编译器也可以自由地抱怨它模板实例化,仅仅是因为i
的任何值都无法使其通过断言。这就是为什么我没有使用,比如说,static\u assert(false)
。因此,实际上,static\u assert
需要一个额外的,“
,但除此之外,这与我所拥有的非常相似(除了我对现有的模板类型进行了标记).请看下面我可怕的回答,了解另一个拙劣的伎俩。
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);
}
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, ""); };
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>(); }
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>(); }