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