此程序在调用时出错
p->Change(1999);
当我在调试器中运行它时,似乎我进入了Change函数,但在检查时,这个指针是0x00。很明显,我使用BOOST::有错误,但我不确定我做错了什么?
我相信以下的汽车的退货类型
//pressure type = Pressure<Printer, Printer>
auto pressure = MakeSubject<Pressure>(
BindObservers(printerObs1, printerObs2), initialPressure);
当我说时,我可能需要使用decltype和auto与Boost::any
boost::any_cast<Pressure<Printer>> // change Pressure<Printer> to use decltype<pressure> ?
但这扩展了我对正在发生的事情的理解。
// static_observer header file
#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;
};
// CRTP Abstract Base class for implementing static subject.
// Example Subclass Usage -- Pressure Sensor:
template <typename... Obs>
class Pressure : public Subject<Pressure<Obs...>, Obs...>
{
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/any.hpp>
int main()
{
std::vector<boost::any> pressures;
Printer printerObs1;
Printer printerObs2;
const int initialPressure = 1;
auto pressure = MakeSubject<Pressure>(
BindObservers(printerObs1, printerObs2), initialPressure);
pressures.push_back(pressure);
pressure.Change(12);
Pressure<Printer> *p = boost::any_cast<Pressure<Printer>>(&pressures[0]);
p->Change(1999); //Bombs
}
有趣的是,我一问这个问题,答案就显而易见了。这项工作:
decltype(pressure) *p = boost::any_cast<decltype(pressure)>(&pressures[0]);
p->Change(1999);