C++在编译时将模板类定义传递给宏

C++ Pass Template class definition to a Macro in compile time

本文关键字:定义 编译 C++      更新时间:2023-10-16

我必须使用库中具有可变参数的函数(createObject),一般用法为:

Class Point 
{
public: 
    Point() {};
    int x;
    int y;
    const char* name;
}
int main() 
{
    Point p;
    createObject("%d",p.x,"%f",p.y,"%d",1,"%s",p.name);
}

现在我想用宏和模板来概括这个函数的用法,比如:

#define PARAM_Matrix(obj) "%d",obj.m,"%d",obj.n,"%d %d",obj[0][0],"%d %d",obj[0][1],"%d %d",obj[0][2]
#define PARAM_Person(obj) "%d",obj.age,"%s",obj.name
#define PARAM_Point(obj) "%d",obj.x,"%f",obj.y,"%d",1,"%s",obj.name
#define MAKE_PARAM(className,obj) PARAM_##className(obj)
class Person;
class Matrix; 
class Point 
{
public: 
    Point() {};
    int x;
    int y;
    const char* name;
}
template<typename T> createGeneralize(T t)
{
    return createObject(MAKE_PARAM(T,t));
}
int main()
{
   Person per;
   Matrix m;
   Point p;
   createGeneralize<Person>(per);
   createGeneralize<Matrix>(m);
   createGeneralize<Point>(p);
}    

我预计在createGeneralize()中,C++编译器会将宏扩展到MAKE_PARAM(Point,t)(或MAKE_PARAM(Matrix,t)…)。然而,事实并非如此,它总是扩展到MAKE_PARAM(T)

您的想法是不可行的,因为预处理器宏在实际编译之前会转换为文本。而模板参数在编译期间被替换。所以你会得到这样的东西:

doMore (Point p)
{
    T u, v; u = v;
}

我建议只使用模板。

您可以使用模板:而不是宏

auto as_tuple(const Person& obj) { return std::make_tuple("%d", obj.age, "%s", obj.name); }
auto as_tuple(const Matrix& obj) { return std::make_tuple("%d", obj.m,"%d",obj.n,"%d %d",obj.obj[0][0],"%d %d",obj.obj[0][1],"%d %d",obj.obj[0][2]); }
auto as_tuple(const Point& obj) { return std::make_tuple("%d", obj.x,"%f",obj.y,"%d",1,"%s",obj.name); }
template<typename Tuple, std::size_t...Is>
void createGeneralize(const Tuple& t, std::index_sequence<Is...>)
{
    return createObject(std::get<Is>(t)...);
}
template<typename T> void createGeneralize(const T& t)
{
    const auto& tuple = as_tuple(t);
    return createGeneralize(tuple, std::make_index_sequence<std::tuple_size<std::decay_t<decltype(tuple)>>::value>());
}

实例