c++之如果constexpr失败,为什么会这样使用C++ 17
cyq1162
阅读:303
2024-06-20 12:54:19
评论:0
我正在尝试使用C++ 17 if constexpr
进行条件编译,但它的行为不符合我的期望。
例如,对于下面的代码,C++仍将编译由X2
宏定义的代码,
#include <map>
#include <string>
#include <iostream>
#include <type_traits>
#define X1 pp("x")
#define X2 pp("x", "x")
void pp(const std::string str)
{
std::cout << str << std::endl;
}
int main()
{
std::map<std::string, int> map;
if constexpr (std::is_null_pointer_v<decltype(map)>)
X2;
else
X1;
}
并显示以下错误消息:
1.c:6:23: error: too many arguments to function ‘void pp(std::__cxx11::string)’
#define X2 pp("x", "x")
^
1.c:18:3: note: in expansion of macro ‘X2’
X2;
^~
如何跳过X2的编译?
请您参考如下方法:
模板之外是不可能的!
从cppreference.com
Outside a template, a discarded statement is fully checked.
if constexpr
is not a substitute for the#if
preprocessing directive:void f() { if constexpr(false) { int i = 0; int *p = i; // Error even though in discarded statement } }
Any idea how to skip compilation of X2?
一种选择是为此提供模板功能。
template<typename T>
void test()
{
if constexpr (std::is_null_pointer_v<T>)
X2;
else
X1;
}
int main()
{
std::map<std::string, int> map;
test<decltype(map)>(); // now chooses the X1
}
感谢
@HolyBlackCat和
@MSalters。如他们所指出的,
上面的解决方案是格式错误的NDR (因此,使用
MSVC compiler进行编译没有任何意义,另一方面
通过提供一些编译器错误 GCC and clang at least catch this)
在 @HolyBlackCat中已详细说明,
回答!
因此,我们可以跳过 X2 的编译吗?
不幸的是,按照您的代码 否!
preprocessor将在编译翻译单元之前执行。
因此,无法将类型信息(即
decltype(map)
)提供给
#if
指令。
因此,对于您的情况,没有其他方法。
这个帖子的好教训:
和
constexpr if
混合。 如果可能的话,编译器!
我建议对您的情况有一个
PP
(当然还有许多其他方法)的函数重载,通过它可以得到格式正确的代码:
See a demo。
#include <string>
#include <iostream>
#include <type_traits>
#include <map>
void pp(const std::string& str)
{
std::cout << str << std::endl;
}
template<typename... T> void pp(const T&... args)
{
// do something with args!
}
template<typename T>
constexpr void test()
{
if constexpr (std::is_null_pointer_v<T>)
pp("x", "x"); // call with args
else
pp("x"); // call with string
}
声明
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。