代码之家  ›  专栏  ›  技术社区  ›  Ivan

Boost.Bind和模板成员函数

  •  -1
  • Ivan  · 技术社区  · 9 年前

    我有个功能 Change 它采用模板类中的两个参数。boost::bind给出一个错误 error: invalid use of non-static member function

    #include <utility>
    #include <tuple>
    #include <iostream>
    
    
    enum class EventType
    {
        UNKNOWN
    };
    
    
    // Note: All Observers must implement OnNotify for any subject types they wish to observe
    //       Any unimplemented subject types that are used will result in a compiler error
    template <typename Base> class Observer
    {
    public:
        Observer() : obsID_(obsIDTracker_++) {}
        template <typename T> void OnNotifyImpl(T &subject, EventType event)
        {
            static_cast<Base *>(this)->OnNotify(subject, event);
        }
        int GetID() const
        {
            return obsID_;
        }
    private:
        int obsID_;
        static int obsIDTracker_;
    };
    template <typename base> int Observer<base>::obsIDTracker_ = 0;
    
    // Recursive helper structs for implementing calls to all observers held within subjects
    template <int N, typename T, typename... Args> struct NotifyHelper
    {
        static void NotifyImpl(T &subject, EventType event,
                               std::tuple<Args...> &obs)
        {
            std::get<sizeof...(Args) - N>(obs).OnNotifyImpl(subject, event);
            NotifyHelper<N - 1, T, Args...>::NotifyImpl(subject, event, obs);
        }
    };
    template <typename T, typename... Args> struct NotifyHelper<0, T, Args...>
    {
        static void NotifyImpl(T &subject, EventType event,
                               std::tuple<Args...> &obs) {}
    };
    
    // See MakeSubject function for instance usage
    template <typename T, typename... Obs> class Subject
    {
    public:
        static const int NumberOfObservers = sizeof...(Obs);
        Subject(std::tuple<Obs &...> &&obs) : observers(obs) {}
    
        void NotifyAll(EventType event)
        {
            NotifyHelper<NumberOfObservers, T, Obs &...>::NotifyImpl(
                *static_cast<T *>(this), event, observers);
        }
    
    private:
        std::tuple<Obs &...> observers;
    };
    
    //class PressureInterface
    //{
    //public:
    //    virtual ~PressureInterface() {}
    //    virtual void Change(int value) {}
    //};
    
    // CRTP Abstract Base class for implementing static subject.
    // Example Subclass Usage -- Pressure Sensor:
    template <typename... Obs>
    class Pressure : public Subject<Pressure<Obs...>, Obs...> //,public PressureInterface
    {
    public:
        typedef Subject<Pressure<Obs...>, Obs...> BaseType;
        Pressure(std::tuple<Obs &...> &&observers, int pressure)
            : BaseType(std::move(observers)), pressure_(pressure) {}
        void Change(int value)
        {
            pressure_ = value;
            this->NotifyAll(EventType::UNKNOWN);
        }
        int GetPressure() const
        {
            return pressure_;
        }
    
    private:
        int pressure_;
    };
    
    // CRTP Abstract Base class for implementing static subject.
    // Example Subclass Usage -- Printing Observer:
    class Printer : public Observer<Printer>
    {
    public:
        Printer() : timesTriggered_(0) {}
        template <typename... Args>
        void OnNotify(Pressure<Args...> &subject, EventType event)
        {
            std::cout << "Observer ID: " << this->GetID() << std::endl;
            switch (event)
            {
            case EventType::UNKNOWN:
            {
                std::cout << "Unknown Event -- Event #" << timesTriggered_++
                          << std::endl;
                std::cout << "Pressure: " << subject.GetPressure() << std::endl;
                break;
            }
            default:
            {
                break;
            }
            }
        }
    
    private:
        int timesTriggered_;
    };
    
    
    // Binding function for use with MakeSubject
    //   Arguments: observer objects to observe subject notifications
    //   Return:    tuple of references to observers
    template <typename... Obs> std::tuple<Obs &...> BindObservers(Obs &... obs)
    {
        return std::tuple<Obs &...>(obs...);
    }
    
    // Creator to ease subject creation
    //   Template Arguments: Subject subclass type
    //   Arguments: Result from BindObservers
    //              Any constructor arguments for Subject subclass
    //   Return:    Subject subclass
    // Example Usage:
    // auto pressure = MakeSubject<Pressure>(BindObservers(printerObs), initialPressure);
    template <template <typename...> class T, typename... Args, typename... Obs>
    T<Obs...> MakeSubject(std::tuple<Obs &...> &&obs, Args &&... args)
    {
        return T<Obs...>(std::move(obs), args...);
    }
    
    #include <boost/bind.hpp>
    
    int main()
    {
        Printer printerObs1;
        Printer printerObs2;
    
        const int initialPressure = 1;
    
        auto pressure = MakeSubject<Pressure>(
                            BindObservers(printerObs1, printerObs2), initialPressure);
    
        //Compiler gives error here:
        boost::bind(&Pressure<Printer, Printer>::Change, pressure.Change, _1, 12);
    
        pressure.Change(12);
    
        pressures[0].change(2000);
    }
    
    1 回复  |  直到 9 年前
        1
  •  1
  •   Arpegius    9 年前

    无需使用 boost::ref 。若要调用boost::bind,请使用指向您需要提供的方法的指针 this 将调用该方法的对象的指针:

    ioService.post(boost::bind(&Pressure<Printer, Printer, Printer>::change, observerMap[astring], astring, v));