2017-07-29 31 views
2

我的工作Visual Studio 2015 community edition函數模板(它是類模板的成員)的顯式特化產生「不允許部分特化」錯誤,爲什麼?

讓我們說我有,像這樣一個簡單的類:
(下面的例子「應該是」可編譯的,因爲它包括所有必要的東西,不幸的是,它會產生一個錯誤)。

#include <stdexcept> 

template <typename T> 
class class_foo 
{ 
// members, methods, constructors. not important stuff... 

// helper functions: 
private: 
    class tag_aaa {}; // to resolve few things at compile-time, not run-time. 
    class tag_bbb {}; // - || - 

    template <typename tag> 
    void erase(); 

    // for some reason this is not interpreted as an error by my compiler: 
    template<> 
    void erase<tag_aaa>(); 

    template<> 
    void erase<tag_bbb>(); 
}; 

// catch-all-do-nothing "version" 
// well, catch-all-throw-an-exception because call to this function is an obvious error. 
// that should never occur. 
template <typename T> 
template <typename tag> inline 
void class_foo<T>::erase() 
{ 
    throw std::runtime_error("Very weird error..."); 
} 

template <> 
template <typename T> inline 
void class_foo<T>::erase<class_foo<T>::tag_aaa>() 
{ 
    // do some stuff... 
} 

template <> 
template <typename T> inline 
void class_foo<T>::erase<class_foo<T>::tag_bbb>() 
{ 
    // do some stuff... 
} 

int main() 
{ 
    class_foo<double> bar; 

    return 0; 
} 

錯誤:

1>D:/develop/workspace/visual_studio/nevada_test_site/source/workspace/nevada_test_site/start.cu(36): error : partial specialization of class "class_foo<T>::erase<class_foo<T>::tag_aaa> [with T=T]" is not allowed 

1>D:/develop/workspace/visual_studio/nevada_test_site/source/workspace/nevada_test_site/start.cu(43): error : partial specialization of class "class_foo<T>::erase<class_foo<T>::tag_bbb> [with T=T]" is not allowed 

1>D:/develop/workspace/visual_studio/nevada_test_site/source/workspace/nevada_test_site/start.cu(51): warning : variable "bar" was declared but never referenced 

我想到自己作爲一個初中愛好者程序員,所以肯定是我錯了,但我相信,這兩個erase<class_foo<T>::tag_aaa>()erase<class_foo<T>::tag_bbb>()template <typename tag> void erase();功能明確的專業。因此,他們是被允許的。我相信這個錯誤是由於語法錯誤,但我找不到錯誤。

問:

  • 是什麼,我試圖做的,是否允許?
  • 如果是,我做錯了什麼?
  • 如果是,專門用於此功能的正確語法是什麼(erase)?
+0

是否有任何人願意幫助我嗎? – cukier9a7b5

回答

2

它看起來像模板函數的完全專業化,但它仍然是部分專業化,因此編譯錯誤。

爲什麼?那麼,看看這個專業:

template <> 
template <typename T> 
inline void class_foo<T>::erase<class_foo<T>::tag_bbb>() { 
    // do some stuff... 
} 

你說這是一個明確的專業化,但仍然有一個模板參數來填充!有參數T尚未知道。所以專業化...仍然是一個模板?這是部分專業化!

功能的部分專業化是不允許的,原因很多。其中之一是,它不會與超載很好地玩。

爲了有效專門的功能,你必須離開被稱爲無模板參數,像這樣:

template<> 
template<> 
inline void class_foo<int>::erase<class_foo<int>::tag_bbb>() { 
    // do some stuff... 
} 

但它不是你想要的。


下面是我如何解決這個問題。超載使用,而不是專業:

template<typename T> 
struct class_foo { 

private: 
    struct tag_aaa {}; 
    struct tag_bbb {}; 

    void erase(tag_aaa) { 
     // Stuff when tag_aaa 
    } 

    void erase(tag_bbb) { 
     // Stuff when tag_bbb 
    } 
}; 

而不是調用的是這樣的:

erase<tag_aaa>(); // with specialization 

您必須調用它像:

erase(tag_aaa{}); // with overloading 
相關問題