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 
    } 
    


    标签:C++
    声明

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    关注我们

    一个IT知识分享的公众号