C++ C+;中对象列表的调用对象方法+;
如何为提供给函数的每个对象设计一种调用对象方法的方法 即 将调用C++ C+;中对象列表的调用对象方法+;,c++,function,object,C++,Function,Object,如何为提供给函数的每个对象设计一种调用对象方法的方法 即 将调用obj1.Reset(),obj2.Reset(),等等 对象不在列表或任何其他STL容器中。可能是可变模板: template <typename ...Objs> struct Resetter; template <typename Obj, typename ...Rest> struct Resetter<Obj, Rest> { static inline void reset(
obj1.Reset()
,obj2.Reset()
,等等
对象不在列表或任何其他STL容器中。可能是可变模板:
template <typename ...Objs> struct Resetter;
template <typename Obj, typename ...Rest> struct Resetter<Obj, Rest>
{
static inline void reset(Obj && obj, Rest &&... rest)
{
std::forward<Obj>(obj).Reset();
Resetter<Rest...>::reset(std::forward<Rest>(rest)...);
}
};
template <> struct Resetter<> { static inline void reset() { }; };
// Type-deducing helper
template <typename ...Objs> inline void ResetAll(Objs &&... objs)
{
Resetter<Objs...>::Reset(std::forward<Objs>(objs)...);
}
概念证明,因为编写可疑的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;
}
链式操作符
重载允许使用\uu VA\u ARGS\uu
。
一个限制是,它只能在所有参数共享一个基类型时使用,而要调用的方法是为该基类型定义的
这应该具有最小的开销,并且不依赖于任何库。如果您可以接受一些严重的预处理器滥用:
#包括
#定义CALL_RESET(z,n,data)BOOST_PP_CAT(p,n).RESET();
#定义生成变量函数(z,n,数据)\
模板\
void ResetAll(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z、BOOST_PP_INC(n)、T和p))\
{ \
BOOST_PP_CAT(BOOST_PP_REPEAT_uz)(BOOST_PP_INC(n),CALL_RESET,)\
}
/*^这将生成函数
模板
无效重置全部(T0和p0、T1和p1、T2和p2等)
{
p0.Reset();p1.Reset();p2.Reset()。。。
}
*/
BOOST\u PP\u REPEAT(BOOST\u PP\u LIMIT\u REPEAT,GENERATE\u VARIADIC\u FUNCTION,)
//^这将创建最多256个以上的所有项目。
比如说,
#include <cstdio>
struct Obj1 { void Reset() { printf("1\n"); } };
struct Obj2 { void Reset() { printf("2\n"); } };
struct Obj3 { void Reset() { printf("3\n"); } };
int main()
{
Obj1 o1;
Obj2 o2;
Obj3 o3;
ResetAll(o1, o2, o3, o2, o1, o3);
return 0;
}
#包括
结构Obj1{void Reset(){printf(“1\n”);};
结构Obj2{void Reset(){printf(“2\n”);};
结构Obj3{void Reset(){printf(“3\n”);};
int main()
{
obj1o1;
obj2o2;
Obj3-o3;
重置所有(o1,o2,o3,o2,o1,o3);
返回0;
}
将在屏幕上打印“1 2 3 2 1 3”(校样:)
(顺便说一句,如果其中一个输入是右值,这将生成一堵无法逾越的错误消息墙。)我假设此函数接受的参数数量可变?(可变函数)我认为通过指针将对象放入容器或为每个对象调用函数一次都没有问题。为什么这些方法不适用于您?很遗憾,我不能使用任何C++11功能。
std::vector
不是C++11。@birrree也不是STL容器。应该注意的是,这只适用于最新版本的编译器,因为它是全新的C++11标准的一部分。嗨@KerrekSB不幸的是,我将无法使用任何C++11特定的功能。你能想出其他办法吗?@JoachimPileborg:是的,不过如果你愿意,你可以使用微软的技巧在旧编译器上模拟可变模板(最多有一定数量的固定参数)。@chriskirk:嗯,请看我对Joachim的评论。实际上,一开始我想的是可变宏,但我被卡住了。让我重新考虑一下,也许这毕竟是可能的。@chriskirk:你是说你有GCC4.6.1?只需将-std=c++0x
添加到命令中即可!无论如何,我不认为只使用预处理器就可以做到这一点,因为不能递归调用宏,也没有宏的参数包扩展。如果可能的话,我会用这个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
#include <boost/preprocessor.hpp>
#define CALL_RESET(z, n, data) BOOST_PP_CAT(p, n).Reset();
#define GENERATE_VARIADIC_FUNCTION(z, n, data) \
template <BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(n), typename T)> \
void ResetAll(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(n), T, & p)) \
{ \
BOOST_PP_CAT(BOOST_PP_REPEAT_, z)(BOOST_PP_INC(n), CALL_RESET, ) \
}
/* ^ this generates the function
template <typename T0, typename T1, typename T2, ...>
void ResetAll(T0& p0, T1& p1, T2& p2, ...)
{
p0.Reset(); p1.Reset(); p2.Reset(); ...
}
*/
BOOST_PP_REPEAT(BOOST_PP_LIMIT_REPEAT, GENERATE_VARIADIC_FUNCTION, )
// ^ and this creates all of the above up to 256.
#include <cstdio>
struct Obj1 { void Reset() { printf("1\n"); } };
struct Obj2 { void Reset() { printf("2\n"); } };
struct Obj3 { void Reset() { printf("3\n"); } };
int main()
{
Obj1 o1;
Obj2 o2;
Obj3 o3;
ResetAll(o1, o2, o3, o2, o1, o3);
return 0;
}