Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 避免C+中互斥函数调用的预处理器+;20 请考虑下面的小功能。它为以编程方式中断调试器提供编译器抽象: inline constexpr void BreakDebug() { #ifdef __GNUC__ __builtin_trap(); #elif defined _MSC_VER __debugbreak(); #endif }_C++_C Preprocessor_Constexpr_C++20 - Fatal编程技术网

C++ 避免C+中互斥函数调用的预处理器+;20 请考虑下面的小功能。它为以编程方式中断调试器提供编译器抽象: inline constexpr void BreakDebug() { #ifdef __GNUC__ __builtin_trap(); #elif defined _MSC_VER __debugbreak(); #endif }

C++ 避免C+中互斥函数调用的预处理器+;20 请考虑下面的小功能。它为以编程方式中断调试器提供编译器抽象: inline constexpr void BreakDebug() { #ifdef __GNUC__ __builtin_trap(); #elif defined _MSC_VER __debugbreak(); #endif },c++,c-preprocessor,constexpr,c++20,C++,C Preprocessor,Constexpr,C++20,我想用C++20代码重写函数并替换预处理器指令。由于\uuuuu内置陷阱和\uuuuu调试中断是特定于编译器且互斥的,我不能使用简单的if constexpr,因为我会得到编译错误 假设我将使用constexpr枚举常量包装编译器宏\GNUC\uuuuu和\MSC\u VER。。。如何做到这一点?您只需要一个未调用函数的声明(并且没有定义,因为它不会被调用): 通过仅声明不存在且永远不会调用的函数,可以避免在签名不正确的情况下出现链接器错误。显然,这些内置函数也可以转换为从属名称。我查过了。因此

我想用C++20代码重写函数并替换预处理器指令。由于
\uuuuu内置陷阱
\uuuuu调试中断
是特定于编译器且互斥的,我不能使用简单的
if constexpr
,因为我会得到编译错误


假设我将使用
constexpr
枚举常量包装编译器宏
\GNUC\uuuuu
\MSC\u VER
。。。如何做到这一点?

您只需要一个未调用函数的声明(并且没有定义,因为它不会被调用):


通过仅声明不存在且永远不会调用的函数,可以避免在签名不正确的情况下出现链接器错误。

显然,这些内置函数也可以转换为从属名称。我查过了。因此,通常的技巧是使潜在的格式错误的代码依赖于:

enum compiler_t{
    gnu,
    msvc
    };

inline constexpr compiler_t compiler = 
#ifdef __GNUC__
  compiler_t:: gnu;
#else
  compiler_t:: msvc;
#endif

template <class...Args>
inline constexpr void BreakDebug(Args...args)
{

   if constexpr (compiler == gnu){
      __builtin_trap(args...);
   } else {
      __debugbreak(args...);
   }
}

int main(){
   BreakDebug();
   return 0;
}
enum编译器{
gnu,
msvc
};
内联constexpr编译器\u t编译器=
#ifdef__GNUC__
编译器:gnu;
#否则
编译器:msvc;
#恩迪夫
模板
内联constexpr void BreakDebug(Args…Args)
{
if constexpr(编译器==gnu){
__内置陷阱(args…);
}否则{
__调试中断(args…);
}
}
int main(){
BreakDebug();
返回0;
}

是否会出现编译错误?如果constexpr(true)。。。else真的会抱怨
else
?它要么抱怨缺少
\uuuu内置\u陷阱
,要么抱怨缺少
\uuuuu debugbreak
。为什么不使用?@idclev463035818
如果constexpr
只在模板中工作,而条件取决于模板参数(即使如此,两个分支都必须有效)。否则,如果@YSC,它的工作方式就像一个常规的
,我想OP在遇到断点后会继续执行。看起来是一个可行的解决方案。但重复外部函数声明仍然让人觉得不干净。我希望有一个更干净的(元编程)解决方案。@Silicomancer您需要一个声明,所以您可以提供一个声明。我不明白你为什么说那是“不干净的”。顺便说一句,如果你遵循“备选方案”,那么就没有repetition@Silicomancer相关:当不是调用内置编译器函数而是调用普通函数时,它们的原型可能会发生变化。或者我可能会忘记包含正确的标题。在这两种情况下,我都会得到一个链接器错误,而不是编译器错误,这不是一件好事。@Silicomancer sfinae可能会让你有所收获,但它会比这更详细和复杂(请参见此处:)你能详细说明一下吗?我不完全理解为什么参数包技巧是必要的,以及它是如何工作的。@Silicomancer如果没有
args…
参数,编译器可以在BreakDebug的定义点执行uu debugbreak或u builtin_trap的名称查找。这将在ìf constexpr`语句的两个分支中执行,编译器可能会发现其中一个名称没有定义。使用
args…
参数,编译器必须知道要执行ADL(参数相关名称查找)的参数的类型,因此它总是在实例化时执行。但是在实例化的时候,如果讨论了constexp分支,“错误的”,那么就没有错误了。
enum compiler_t{
    gnu,
    msvc
    };

inline constexpr compiler_t compiler = 
#ifdef __GNUC__
  compiler_t:: gnu;
#else
  compiler_t:: msvc;
#endif

template <class...Args>
inline constexpr void BreakDebug(Args...args)
{

   if constexpr (compiler == gnu){
      __builtin_trap(args...);
   } else {
      __debugbreak(args...);
   }
}

int main(){
   BreakDebug();
   return 0;
}