2009-04-20 125 views
8

我正在嘗試使用模板專門化來實現帶有句柄void的模板函數。靜態成員函數的模板特化;如何?

下面的代碼讓我在GCC的「非命名空間範圍明確分工」:

template <typename T> 
static T safeGuiCall(boost::function<T()> _f) 
{ 
    if (_f.empty()) 
     throw GuiException("Function pointer empty"); 
    { 
     ThreadGuard g; 
     T ret = _f(); 
     return ret; 
    } 
} 

// template specialization for functions wit no return value 
template <> 
static void safeGuiCall<void>(boost::function<void()> _f) 
{ 
    if (_f.empty()) 
     throw GuiException("Function pointer empty"); 
    { 
     ThreadGuard g; 
     _f(); 
    } 
} 

我試圖移動它的類(類不是模板),並進入命名空間,但那麼我得到錯誤「明確的專業化不能有一個存儲類」。我已閱讀了許多關於此的討論,但人們似乎不同意如何專門化功能模板。有任何想法嗎?

回答

12

當你專注用模板的方法,你必須這樣做的類括號外:

template <typename X> struct Test {}; // to simulate type dependency 

struct X // class declaration: only generic 
{ 
    template <typename T> 
    static void f(Test<T>); 
}; 

// template definition: 
template <typename T> 
void X::f(Test<T>) { 
    std::cout << "generic" << std::endl; 
} 
template <> 
inline void X::f<void>(Test<void>) { 
    std::cout << "specific" << std::endl; 
} 

int main() 
{ 
    Test<int> ti; 
    Test<void> tv; 
    X::f(ti); // prints 'generic' 
    X::f(tv); // prints 'specific' 
} 

當你把它的類之外,你必須刪除'靜態'關鍵字。類之外的靜態關鍵字具有與您可能想要的不同的特定含義。

template <typename X> struct Test {}; // to simulate type dependency 

template <typename T> 
void f(Test<T>) { 
    std::cout << "generic" << std::endl; 
} 
template <> 
void f<void>(Test<void>) { 
    std::cout << "specific" << std::endl; 
} 

int main() 
{ 
    Test<int> ti; 
    Test<void> tv; 
    f(ti); // prints 'generic' 
    f(tv); // prints 'specific' 
} 
3

您可以用同樣的方式宣佈明確的專業化你定義它的類之外的成員函數:

class A 
{ 
public: 
    template <typename T> 
    static void foo() {} 
}; 

template <> 
void A::foo<void>() 
{ 
} 
+0

感謝您的回答。對我來說,不管他們是否在課堂內都沒關係;但我無法以任何方式使它工作。我的語法錯了或者我提供的代碼中有什麼? – Rolle 2009-04-20 09:23:22

+0

重點在於,您可以使用限定的函數聲明器明確地專門化名稱空間中的函數。 C++不允許您重新添加「靜態」關鍵字,因此您只需刪除它即可。我上面的例子展示瞭如何明確地專門化一個靜態成員。 – 2009-04-20 11:43:39

2

您的問題似乎與升壓::功能 - 以下專業工作:

+0

對不起,嘗試過,但不起作用。你在gcc下編譯過嗎?我認爲它適用於VS例如... – Rolle 2009-04-20 10:01:35

+0

這是g ++版本3.4.5 – 2009-04-20 10:08:04

4

這不是直接回答你的問題,但你可以這樣寫

template <typename T> 
static T safeGuiCall(boost::function<T()> _f) 
{ 
     if (_f.empty()) 
       throw GuiException("Function pointer empty"); 
     { 
       ThreadGuard g; 
       return _f(); 
     } 
} 

它應該工作,即使_f()返回'無效'

編輯:在更一般的情況下,我認爲我們應該更喜歡函數重載而不是專業化。這裏是一個很好的解釋:http://www.gotw.ca/publications/mill17.htm

1

我有類似的問題。如果你看原帖,我將第一個靜態內容留下,但是第二個出現,兩個錯誤都消失了。