2012-11-12 89 views
6

我知道一種用於在頭部聲明一個模板類方法和在一個源文件中定義它的語法變爲這樣:C++ - 在模板類模板函數獨立聲明/定義

myclass.h

template <typename T> 
class MyClass { 
    public: 
    void method(T input); 
    private: 
    T privVar; 
}; 

myclass.cpp

template <typename T> 
void MyClass<T>::method(T input) { 
    privVar = input; 
} 

但是,如果該方法也是一個模板? 我有添加方法到basic_string類,我想知道如何編寫函數的實現。

MyString.h

template <class _Elem = TCHAR, 
      class _Traits = std::char_traits<_Elem>, 
      class _Ax  = std::allocator<_Elem>> 
class String 
    : public std::basic_string<_Elem, _Traits, _Ax> { 
    private: 
    // Types for the conversion operators. 
    typedef  _Elem* _StrTy; 
    typedef const _Elem* _ConstStrTy; 

    //... 

    public: 
     // Conversion operators so 'String' can easily be 
     // assigned to a C-String without calling 'c_str()'. 
    operator _StrTy() const { 
     return const_cast<_StrTy>(this->c_str()); 
    } 

    operator _ConstStrTy() const { 
     return this->c_str(); 
    } 

    // ... Constructors ... 

    /*------------ Additional Methods ------------*/ 

    //! Converts a value of the given type to a string. 
    template <class _ValTy> static String ConvertFrom(_ValTy val); 

    //! Converts a string to the given type. 
    template <class _ValTy> static _ValTy ConvertTo(const String& str); 
    template <class _ValTy> _ValTy ConvertTo(void) const; 

    //! Checks if a string is empty or is whitespace. 
    static bool IsNullOrSpace(const String& str); 
    bool IsNullOrSpace(void) const; 

    //! Converts a string to all upper-case. 
    static String ToUpper(String str); 
    void ToUpper(void); 

    // ... 
}; 

我怎麼能實現template <class _ValTy> static String ConvertFrom(_ValTy val);?因爲現在不僅需要指定類模板,而且還需要函數模板。我打賭,我要寫的代碼是無效的,但它應該表現出什麼,我試圖完成:

MyString.cpp

template <class _Elem, class _Traits, class _Ax> 
template <class _ValTy> 
String<_Elem, _Traits, _Ax> String<_Elem, _Traits, _Ax>::ConvertFrom(_ValTy val) { 
    // Convert value to String and return it... 
} 

我不是先進的所有模板。我非常懷疑上述內容是否有效,寫起來似乎很麻煩,而且不易讀。我將如何去實現模板方法,以及返回它自己的類類型的靜態模板方法?因爲我不想在標題中定義它們。

+1

您應該閱讀:[爲什麼模板只能在頭文件中實現?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-首部的文件)。 –

+0

@JesseGood這表明我有一種方法可以從源文件中的模板類單獨實現* normal *方法,而不是如何從模板類實現* templated *方法。也許我在帖子中忽略了一些東西,我不想成爲那個人。我應該放棄並繼續在頭文件中內聯定義類方法嗎? –

+0

如果您只是試圖從模板函數/類的功能中分離出原型,則可以嘗試使用.inl範例:其中實際功能是.inl文件,並且將該文件包含在頭文件的末尾。 – Alex

回答

9

在我回答你的問題之前,讓我先說:不要這樣做。通過使用自由函數來擴展std::string,就像標準庫實現許多算法一樣。此外,我建議只做範圍而不是string,但這更主觀。

另請注意,std::string可以避免向C字符串隱式轉換,而不會讓您的生活更難,而是保護您的代碼免受可能由意外隱式轉換引起的各種晦澀難懂的錯誤。我會認真考慮實施它們很長時間。考慮一下:編寫代碼時需要花一些時間才能輸入.c_str()一次,而對於永恆的其他人來說,任何讀取代碼的人都會立即知道它被用作C風格的字符串,而不是作爲std::string

要回答你的問題,只是把代碼中的標題:

//! Converts a value of the given type to a string. 
template <class _ValTy> static String ConvertFrom(_ValTy val) 
{ 
    // Code here 
} 

最後請注意,開始用下劃線+大寫字母(和許多開始_其他的東西)的名稱均用於編譯器,因此所有投注都與您的程序功能有關。

+1

+1用於回答問題並給我一些省時的建議。謝謝。 –

2

您的函數定義是有效的,並且它不能在類聲明之外以較不詳細的方式定義。由於您想將函數定義放在.cpp文件中,因此不能將函數定義與更簡潔的函數聲明相結合。通過將函數定義放入.cpp文件中,您還必須顯式實例化模板類的所有必需專業化。

13

模板之外的模板成員函數定義的語法是這樣的:

template <class T> struct A 
{ 
    template <class X> void f(); 
}; 

template<class T> template<class X> void A<T>::f() 
{ 
} 

所以,你的代碼是正確的。

想要說明的是,在.cpp中定義模板成員不是很有用。在這種情況下,您應該使用此模板需要的所有類型顯式實例化它們。或者不要在.cpp以外使用它們,這是沒有意義的。

+0

^謝謝!你拯救了我的生命:) –

+0

@MathuSumMut很高興知道:-) – Rost