Подтверждение концепции, потому что писать сомнительный код на C ++ весело:
#include <vector>
#include <iostream>
using namespace std;
#define Invoke(A, T,M,...)\
do{\
struct _{ \
_& operator,(T* value){ \
value->M A ; \
return *this; \
} \
} _; _, __VA_ARGS__; \
}while(0)
#define m_a_all(...) Invoke( (), Obj,m_a,__VA_ARGS__)
#define m_b_all(...) Invoke( (), Obj,m_b,__VA_ARGS__)
#define m_c_all(A, ...) Invoke(A, Obj,m_c,__VA_ARGS__)
class Obj{
public:
virtual void m_a(){
cout << "Obj::m_a " << this << endl;
}
virtual void m_b(){
cout << "Obj::m_b " << this << endl;
}
virtual void m_c(int a, double b){
cout << "Obj::m_c(" << a <<"," << b<< ") " << this << endl;
}
};
class Derived : public Obj{
public:
virtual void m_a(){
cout << "Derived::m_a " << this << endl;
}
virtual void m_b(){
cout << "Derived::m_b " << this << endl;
}
virtual void m_c(int a, double b){
cout << "Derived::m_c(" << a <<"," << b<< ") " << this << endl;
}
};
int main(){
Obj *o1 = new Obj(), *o2 = new Obj(), *o3 = new Derived();
m_a_all(o1, o2, o3);
cout<<endl;
m_a_all(o1);
cout<<endl;
m_b_all(o1, o2, o3);
cout<<endl;
m_c_all( (3,42.0), o1, o2, o3);
return 0;
}
Пример вывода:
Obj::m_a 0x9e0a008
Obj::m_a 0x9e0a018
Derived::m_a 0x9e0a028
Obj::m_a 0x9e0a008
Obj::m_b 0x9e0a008
Obj::m_b 0x9e0a018
Derived::m_b 0x9e0a028
Obj::m_c(3,42) 0x9e0a008
Obj::m_c(3,42) 0x9e0a018
Derived::m_c(3,42) 0x9e0a028
Перегрузка operator,
в цепочке позволяет использовать __VA_ARGS__
.Одно ограничение заключается в том, что его можно использовать только в том случае, если все аргументы имеют базовый тип, для которого определен вызываемый метод.
Это должно иметь минимальные издержки и не зависит от каких-либо библиотек.