2017-01-14 77 views
1

考慮以下幾點:專業化的功能,用於特定的模板類型

template <typename TResult> inline TResult _from_string(const string& str); 
template <> inline unsigned long long _from_string<unsigned long long>(const string& str) { 
    return stoull(str); 
} 

我可以調用的功能,例如:

auto x = _from_string<unsigned long long>("12345"); 

現在我想再寫專門爲vector S,即:

template <typename T> inline vector<T> _from_string<vector<T>>(const string& str) { 
    // stuff that should be done only if the template parameter if a vector of something 
} 

以便我可以這樣做:

auto x = _from_string<vector<int>>("{1,2,3,4,5}"); 

然而,當我編譯功能(MSVC在2015年),我得到錯誤C2768:「非法使用顯式模板參數」,這讓我不應該在一個專門爲具有新的模板參數某種意義上。

我該如何重寫vector專業化,以便它可以工作?

+0

您一定要閱讀Herb Sutter的[本文](http://www.gotw.ca/publications/mill17.htm)。 – Rakete1111

回答

3

函數模板只能是full specialized,它們不能是partial specialized;但類模板可以。

// primary class template 
template <typename T> 
struct X { 
    static T _from_string(const string& str); 
}; 

// full specialization for unsigned long long 
template <> 
struct X<unsigned long long> { 
    static unsigned long long _from_string(const string& str) { 
     return stoull(str); 
    } 
}; 

// partial specialization for vector<T> 
template <typename T> 
struct X<vector<T>> { 
    static vector<T> _from_string(const string& str) { 
     // stuff that should be done only if the template parameter if a vector of something 
    } 
}; 

// helper function template 
template <typename TResult> 
inline TResult _from_string(const string& str) { 
    return X<TResult>::_from_string(str); 
} 

然後

auto x1 = _from_string<unsigned long long>("12345"); 
auto x2 = _from_string<vector<int>>("{1,2,3,4,5}"); 

LIVE

3

不能部分專門功能。

你應該很少完全專注於功能。

解決此問題的更好方法是使用重載。超載對返回類型只需要一個額外的ARG:

template<class T> struct tag_t{constexpr tag_t(){}; using type=T;}; 
template<class T>constexpr tag_t<T> tag{}; 

template <typename TResult> inline TResult _from_string(const string& str){ 
    return _from_string(tag<TResult>, str); 
} 

現在,我們從來沒有專門_from_string,我們只是超載2 ARG版本。

inline unsigned long long _from_string(tag_t<unsigned long long>, const string& str) { 
    return stoull(str); 
} 

以上甚至不是模板。

template <class T, class A> 
std::vector<T,A> _from_string(tag_t<std::vector<T,A>>, const string& str) { 
    // stuff that should be done only if the target type is a vector of something 
} 

以上是一個模板,但不是一個專門化的。

作爲獎勵,如果你在namespace foo有一個自定義類型bob,您只需在namespace foo_from_string(tag_t<bob>, std::string const&),以及一些被稱爲「ADL」會自動找到它在大多數情況下。

基於重載的標籤調度非常簡單明瞭,您可以在相關命名空間中自定義事件。