2013-04-04 80 views
2

我有一个方法模板类:实施了“静态观察者模式”

struct Subject 
{ 
    template <typename T> 
    void doSomething() 
    { 
    .. 
    } 
}; 

现在,每当doSomething被称为(与任何T)我想有一个“观察者”通知:

template <typename T> 
    void onDoSomething() 
    { 
    .. 
    } 

重要的是观察者是一个方法模板(包含方法的类模板也可以)。如果不是这样,我可以实现常见的观察者模式。

可以修改Subject::doSomething()以便调用方法。但是,类Subject不应“知道”具体的Observer/observer方法。

这背后的想法是:我在两个项目中使用Subject。我只需要其中一个观察员(并且有)。

有什么办法可以达到这个目的吗?

+0

我忘了提及我不能使用C++ 11功能。但即使我能做到,我也不明白这是如何解决我的具体问题的? – Philipp 2013-04-04 10:08:52

+0

@Philipp你是对的,它没有帮助。我误解了你的问题。 – juanchopanza 2013-04-04 10:20:53

回答

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

observer_def.hpp在项目中的

template <typename> 
inline void notifyDoSomething() {} 

observer_def。HPP B工程

template <typename T> 
inline void notifyDoSomething() 
{ 
    MyObserver::onDoSomething<T>(); 
} 
+0

感谢您的想法。方法1是不可取的,因为'doSomething'在其他一些我不想改变的方法中深度调用。方法2对我来说看起来不像现代C++风格。我想我找到的解决方案(请参阅其他答案)更多是我需要的,但无论如何+1。 – Philipp 2013-04-04 11:08:09

+0

@Philipp:实际上,您的解决方案需要与Angew使用的预处理器完全相同......但我会推荐使用#ifdef ... #else ... #endif块而不是两个不同的文件(它是较少混淆)。 – 2013-04-04 11:41:29

+0

@MatthieuM。这就是为什么我说“不同/不同配置”。我试图覆盖'#ifdef'选项。 – Angew 2013-04-04 11:44:20

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模板,如上所示。

编辑:这在我的测试中工作得很好,但问题是如何在具有不同编译单元的场景中使用它 - 我应该在哪里定义专业化?

+1

专业化应该在使用点可见。因此,在定义'Subject :: doSomething'之前应该包含它......这需要预处理器hackery('#ifdef ...'),因此人们想知道为什么要使用模板专门化而不是非模板的不同定义'Observer'类。 – 2013-04-04 11:39:25