С ++ функторы и ноль - PullRequest
       37

С ++ функторы и ноль

0 голосов
/ 18 июля 2009

Сначала отказ от ответственности, я заменяю кучу кода, который использует boost :: function и boost :: bind. Тем не менее, я перехожу на кодовую базу, которая не позволяет RTT. Я хотел бы продолжать использовать повышение, но не знаю, есть ли способ обойти это ограничение.

Итак, я пытаюсь подражать некоторым его функциям, но гораздо более упрощенным. У меня есть класс обратного вызова:

   template <class Class, typename ReturnType = void> class Callback0 {
   typedef ReturnType (Class::*Method)();

   public:
       Callback0(Class* object, Method method)
           : m_object(object)
           , m_method(method)
       {
          ;
       }

       Callback0(const Callback0& callback)
           : m_object(callback.m_object)
           , m_method(callback.m_method)
       {
          ;
       }

       operator bool() {
           return m_object != 0;
       }

       operator bool() const {
           return m_object != 0;
       }

       ReturnType operator()() {
           return (m_object->*m_method)();
       }

       Callback0<Class, ReturnType>& operator=(const Callback0<Class, ReturnType>& callback) {
           if(this != &callback) {
               m_object = callback.m_object;
               m_method = callback.m_method;
           }

           return *this;
       }

   private:
       Class*   m_object;
       Method   m_method;
};

Это позволяет мне делать простые обратные вызовы с нулевыми параметрами:

class Meh {
    public:
        Meh() {;}
        ~Meh() {;}

        void f0() {
            footprint6v("%s\n", __FUNCTION__);
        }
};


static void meh() {
    Meh* m = new Meh;

    Callback0<Meh, void> c0(m, &Meh::f0);

    c0();
}

Я бы хотел иметь возможность присваивать моим объектам обратного вызова ноль в качестве параметров по умолчанию, например:

class Wtf {
    public:
        Wtf() : m_callback(0) {;}
        ~Wtf() {;}

        void doSomething(const Callback0<Wtf, void>& callback = 0) {
            m_callback = callback;
        }

    private:
        Callback0<Wtf, void> m_callback;
};

Это работает при использовании boost :: function, как вы можете сделать:

class Wtf {
    public:
        Wtf() : m_callback(0) {;}
        ~Wtf() {;}

        void doSomething(const boost::function<void()>& callback = 0) {
            m_callback = callback;
        }

    private:
        boost::function<void()> m_callback;
};

Я полагаю, что Boost делает здесь немного магии. Я знаю, что могу просто изменить параметр на указатель, а не на ссылку, но, как я уже сказал, я заменяю большой объем кода и хотел бы свести к минимуму влияние перехода с boost.

1 Ответ

5 голосов
/ 18 июля 2009

Повышение не делает ничего волшебного. 0 - просто нулевой указатель на функцию для конструктора указателя на функцию.

Я бы предложил в вашем случае просто предоставить конструктор по умолчанию

Callback0() : m_object(NULL), m_method(NULL) {}

И сделай что-нибудь похожее

void doSomething(const Callback0<Wtf, void>& callback = Callback0<Wtf, void>()) {
...