避免 C++20 中互斥函数调用的预处理器
Avoiding preprocessor for mutual exclusive function call in C++20
请考虑以下小功能。它为以编程方式破坏调试器提供了编译器抽象:
inline constexpr void BreakDebug()
{
#ifdef __GNUC__
__builtin_trap();
#elif defined _MSC_VER
__debugbreak();
#endif
}
我想重写函数并使用 C++20 代码替换预处理器指令。由于 __builtin_trap
和 __debugbreak
是特定于编译器且互斥的,我不能使用简单的 if constexpr
因为我会得到编译错误。
假设我将使用 constexpr
枚举常量包装编译器宏 __GNUC__
和 _MSC_VER
...那该怎么做?
你只需要一个不被调用的函数的声明(不需要定义,因为它不会被调用):
inline constexpr void BreakDebug()
{
#ifdef __GNUC__
constexpr bool GNU = true;
constexpr void __debugbreak();
#elif defined _MSC_VER
constexpr bool GNU = false;
constexpr void __builtin_trap();
#endif
if constexpr (GNU){
__builtin_trap();
} else {
__debugbreak();
}
}
通过仅声明不存在且永远不会调用的函数,您可以避免在签名不正确的情况下出现链接器错误。
显然,那些内置函数也可以变成依赖名称。我检查了这个 here。因此,使潜在的格式错误的代码依赖起作用的常用技巧:
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;
}
请考虑以下小功能。它为以编程方式破坏调试器提供了编译器抽象:
inline constexpr void BreakDebug()
{
#ifdef __GNUC__
__builtin_trap();
#elif defined _MSC_VER
__debugbreak();
#endif
}
我想重写函数并使用 C++20 代码替换预处理器指令。由于 __builtin_trap
和 __debugbreak
是特定于编译器且互斥的,我不能使用简单的 if constexpr
因为我会得到编译错误。
假设我将使用 constexpr
枚举常量包装编译器宏 __GNUC__
和 _MSC_VER
...那该怎么做?
你只需要一个不被调用的函数的声明(不需要定义,因为它不会被调用):
inline constexpr void BreakDebug()
{
#ifdef __GNUC__
constexpr bool GNU = true;
constexpr void __debugbreak();
#elif defined _MSC_VER
constexpr bool GNU = false;
constexpr void __builtin_trap();
#endif
if constexpr (GNU){
__builtin_trap();
} else {
__debugbreak();
}
}
通过仅声明不存在且永远不会调用的函数,您可以避免在签名不正确的情况下出现链接器错误。
显然,那些内置函数也可以变成依赖名称。我检查了这个 here。因此,使潜在的格式错误的代码依赖起作用的常用技巧:
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;
}