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

时间:2015-03-26 04:35:39

标签: c++ dynamic macros

我必须在库中使用带有变量参数的函数(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)

2 个答案:

答案 0 :(得分:0)

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

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

我建议只使用模板。

答案 1 :(得分:0)

您可以使用模板代替宏:

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>());
}

Live example