如何使宏处理不同类型的参数?

How can I make a macro handle different types of arguments?

本文关键字:参数 同类型 何使宏 处理      更新时间:2023-10-16

如何编写一个根据其参数类型执行不同操作的宏?

我有一个宏,需要处理可以具有两种类型之一的参数。

#include <typeinfo>
enum class Coolness { kUndefined, kUncool, kCool };
enum class Tallness { kUndefined, kShort, kTall };
void MakePerson (Coolness coolness, Tallness tallness) {}
// Provide a way to make a person by only providing Coolness or Tallness.
#define MAKE_PERSON(x)                         
({                                             
if (typeid(x) == typeid(Coolness)) {         
MakePerson(((x)), Tallness::kUndefined); 
} else {                                     
MakePerson(Coolness::kUndefined, (x));   
}                                            
})
int main()
{
MAKE_PERSON(Coolness::kUncool);
MAKE_PERSON(Tallness::kTall);
}

(我们可以在这里使用默认参数,但在实际代码中,我们实际上必须使用宏。

编译器在 main 中的两个调用上都抛出错误:

main.cpp: In function ‘int main()’:
main.cpp:23:43: error: cannot convert ‘Coolness’ to ‘Tallness’ for argument ‘2’ to ‘void MakePerson(Coolness, Tallness)’
MakePerson(Coolness::kUndefined, (x)); 
^
main.cpp:29:3: note: in expansion of macro ‘MAKE_PERSON’
MAKE_PERSON(Coolness::kUncool);
^~~~~~~~~~~
main.cpp:21:45: error: cannot convert ‘Tallness’ to ‘Coolness’ for argument ‘1’ to ‘void MakePerson(Coolness, Tallness)’
MakePerson(((x)), Tallness::kUndefined); 
^
main.cpp:30:3: note: in expansion of macro ‘MAKE_PERSON’
MAKE_PERSON(Tallness::kTall);
^~~~~~~~~~~

(https://www.onlinegdb.com/online_c++_compiler 完成)

我们不能像这个问题一样使用__builtin_types_compatible_p因为我们的编译器没有这个。

如何编写一个根据其参数类型执行不同操作的宏?

使用简单的函数重载,不要试图使宏比它需要的更智能:

enum class Coolness { kUndefined, kUncool, kCool };
enum class Tallness { kUndefined, kShort, kTall };
void MakePerson (Coolness coolness, Tallness tallness)
{
...
}
inline void MakePerson (Coolness coolness)
{
MakePerson(coolness, Tallness::kUndefined);
}
inline void MakePerson (Tallness tallness)
{
MakePerson(Coolness::kUndefined, tallness);
}
#define MAKE_PERSON(x) 
{ 
// use __FILE__ and __LINE__ as needed... 
MakePerson(x); 
}
int main()
{
MAKE_PERSON(Coolness::kUncool);
MAKE_PERSON(Tallness::kTall);
}

现场演示

欢迎其他建议,但我们最终做的是使用static_cast告诉编译器参数是什么类型:

#include <typeinfo>
enum class Coolness { kUndefined, kUncool, kCool };
enum class Tallness { kUndefined, kShort, kTall };
void MakePerson (Coolness coolness, Tallness tallness) {}
// Provide a way to make a person by only providing Coolness or Tallness.
// Static cast is used because the compiler fails to typecheck the 
// branches correctly without it.
#define MAKE_PERSON(x)                                              
({                                                                  
if (typeid(x) == typeid(Coolness)) {                              
MakePerson(static_cast<Coolness>((x)), Tallness::kUndefined); 
} else {                                                          
MakePerson(Coolness::kUndefined, static_cast<Tallness>((x))); 
}                                                                 
})
int main()
{
MAKE_PERSON(Coolness::kUncool);
MAKE_PERSON(Tallness::kTall);
}
...Program finished with exit code 0