Вызовите объектный метод для списка объектов в C ++ - PullRequest
2 голосов
/ 02 ноября 2011

Как я могу разработать способ вызова метода объекта для каждого объекта, предоставленного функции?

т.е.,

ResetAll(obj1, obj2, obj3, ...)

будет звонить obj1.Reset(), obj2.Reset() и т. Д ...

Объекты не находятся в списке или любом другом контейнере STL.

Ответы [ 3 ]

5 голосов
/ 02 ноября 2011

Возможно, шаблон с вариацией:

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

Использование:

ResetAll(ob1, obj2, some_obj, another_obj);
2 голосов
/ 02 ноября 2011

Подтверждение концепции, потому что писать сомнительный код на 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__.Одно ограничение заключается в том, что его можно использовать только в том случае, если все аргументы имеют базовый тип, для которого определен вызываемый метод.

Это должно иметь минимальные издержки и не зависит от каких-либо библиотек.

1 голос
/ 02 ноября 2011

Если вы могли бы принять некоторые серьезные злоупотребления препроцессором с Boost.Preprocessor :

#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;
}

напечатает «1 2 3 2 1 3» на экране (подтверждение: http://ideone.com/FRNvJ).

(Кстати, это создаст непреодолимую стену сообщений об ошибках, если один из входных данных является r-значением.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...