我有一个带有方法模板的类:
struct Subject
{
template <typename T>
void doSomething()
{
..
}
};
现在每当调用doSomething
时(任何T
)我都希望通知“观察者”:
template <typename T>
void onDoSomething()
{
..
}
观察者是一个方法模板很重要(包含方法的类模板也可以工作)。如果不是,我可以实现常见的观察者模式。
可以修改Subject::doSomething()
以便它调用方法。但是,类Subject
不应该“知道”具体的Observer / observer方法。
这背后的想法是:我在两个项目中使用Subject
。我只需要其中一个观察者(并且有)。
有没有办法实现这个目标?
答案 0 :(得分:2)
艰难的一个。它似乎归结为
通知必须在编译时可解析(它是模板)
并且同时
通知不应在编译时解析(
Subject
不应该知道观察者)
我可以想到两种方法:
1.
添加doSomething
的重载:
template <typename T, typename Observer>
void doSomething()
{
doSomething<T>();
Observer::onDoSomething<T>();
}
然后调用项目A中的单参数版本和项目B中的双参数版本。
2.
让定义Subject
的文件包含一个标题,每个项目中的标题将不同/不同:
<强> Subject.h 强>
#include "observer_def.hpp"
struct Subject
{
template <typename T>
void doSomething()
{
..
notifyDoSomething<T>();
}
};
项目A中的observer_def.hpp :
template <typename>
inline void notifyDoSomething() {}
项目B中的observer_def.hpp :
template <typename T>
inline void notifyDoSomething()
{
MyObserver::onDoSomething<T>();
}
答案 1 :(得分:1)
我终于通过模板专业化找到了令人满意的解决方案:
///signaling struct. Could be replaced with any other type.
struct SpecializedObserver{};
///unspecialized:
template <typename>
struct Observer
{
template <typename T>
static void onDoSomething()
{
//default: do nothing.
}
};
///optional. Specialize in project A or leave aside in project B:
template<>
struct Observer<SpecializedObserver>
{
template <typename T>
static void onDoSomething()
{
std::cout << "doing something with " << typeid(T).name() << std::endl;
}
};
struct Subject
{
template <typename T>
void doSomething()
{
Observer<SpecializedObserver>::onDoSomething<T>();
..
}
};
如果我不想要观察者,此解决方案不需要任何操作。如果我想要一个,我专门研究Observer模板,如上所示。
编辑:这在我的测试中运行良好,但问题是如何在具有不同编译单元的场景中使用它 - 我应该在哪里定义专业化?