2013-04-04 136 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