c++ - 如果constexpr失败,为什么会这样使用C++ 17?

标签 c++ if-statement templates c++17 constexpr

我正在尝试使用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++ - 如果constexpr失败,为什么会这样使用C++ 17?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63046397/

    相关文章:

    c++ - 如何知道哪个用户帐户运行特定的 Windows 服务?

    c++ - 包括具有 "/"字符的库

    c++ - Visual Studio Code c++11 扩展警告

    java - 传递给调用方法的命令行参数

    templates - C++ - 检查所有模板参数是否都是 2 的幂

    c# - 创建屏幕键盘

    linux - 如何检查文件是否是 Bash shell 中的 tar 文件?

    r - 如何检查可以找到多少列字符

    c++ - std::is_invocable 的奇怪行为

    C++ 如何从一个模板类转换为另一个模板类?