2010-08-12 211 views
5

的Modern C++ Design給了下面的例子:使用模板模板類參數作爲參數

template <class T> struct EnsureNotNull 
{ 
    static void Check(T*& ptr) 
    { 
     if (!ptr) ptr = GetDefaultValue(); 
    } 
}; 

template 
< 
    class T, 
    template <class> class CheckingPolicy = EnsureNotNull, 
    template <class> class ThreadingModel 
> 
class SmartPtr 
    : public CheckingPolicy<T> 
    , public ThreadingModel<SmartPtr> 
{ 
... 
    T* operator->() 
    { 
    typename ThreadingModel<SmartPtr>::Lock guard(*this); 
    CheckingPolicy<T>::Check(pointee_); 
    return pointee_; 
    } 
private: 
    T* pointee_; 
}; 

我想不出怎樣的ThreadingModel模板會以一種方式構成,即它可以接受的SmartPtr爲參數,在我心中一些瘋狂的遞歸將會發生。這怎麼可能?

編輯:

我試過Potatoswatter(不好意思笑)評論:

template <class SmartPtr> struct SingleThreadingModel 
{ 
    class Lock 
    { 
    public: 
     Lock(SmartPtr&) 
     { 
     } 
    }; 
}; 

但它did'nt工作。

這裏是GCC是給我的錯誤:

main.cpp:28:35: error: type/value mismatch at argument 1 in template parameter list for ‘template<class> class ThreadingModel’ 
main.cpp:28:35: error: expected a type, got ‘SmartPtr’ 
+0

啊,是的。模板模板參數。有史以來最令人困惑的事情之一。 – 2010-08-12 21:59:52

+2

你的新代碼看起來很好。你得到什麼錯誤,在哪裏?另外,一個Tomatoswatter聽起來會讓它變得一團糟,我試圖避免這樣做。 – Potatoswatter 2010-08-13 01:09:04

回答

5

您試圖通過SmartPtr作爲模板類型參數爲ThreadingModel。然而,SmartPtr是一個模板,而不是具體的類型,並且injected class-name在繼承列表中不可用。

還要注意的是,你不能只使用默認參數在任意位置模板參數(§14.1/ 11):

如果模板參數具有默認模板參數,所有後續模板參數應該有一個默認的模板參數。

你有固定的這些問題代碼:

template 
< 
    class T, 
    template <class> class ThreadingModel, 
    template <class> class CheckingPolicy = EnsureNotNull 
> 
class SmartPtr 
    : public CheckingPolicy<T> 
    , public ThreadingModel<SmartPtr<T, ThreadingModel, CheckingPolicy> > 
//      ^.... now passing a concrete class ....^
{ 
    T* operator->() { 
     // the following use of SmartPtr is fine as it is the injected class-name: 
     typename ThreadingModel<SmartPtr>::Lock guard(*this); 
     // ... 
    } 
}; 

注意的是,雖然現代C++設計是一個很好的書,它不能代替模板良好的基礎書像Vandevoorde/Josuttis

+0

有道理。我已經下載了Loki的源代碼,並注意到類定義中沒有ThreadingModel。 – scooterman 2010-08-13 13:19:29

0

遞歸是可以的,因爲通過專業化作爲模板參數並不直接導致它被實例化。

ThreadingModel<SmartPtr>在基地名單只是針對ThreadingModel< SmartPtr< T, CheckingPolicy, ThreadingModel > >簡寫,它使用了「當前專業化。」)

我不知道是什麼ThreadingModel是應該做的,所以我無法實現它,但它應該有形式

template< class Client > class MyThreading 

的聲明,並不能內部ClientMyThreading成員函數訪問任何東西。如果您使用ClientClient取決於MyThreading,則發生無限遞歸。

+0

馬鈴薯,你能提供如何執行ThreadingModel的聲明嗎?我在這裏嘗試了很多方法,但都沒有成功。 – scooterman 2010-08-12 23:04:56

+0

嗯,試過了。它沒有使用或不使用客戶端insite類。請注意,在該示例中,它構建了一個傳遞這個參數的警衛,因此它應該可以工作。 – scooterman 2010-08-12 23:54:43