[英]C++ template with default parameter
這是我第一次嘗試使用其迭代器實現與STL兼容的自定義容器,但是我在模板語法和用法上遇到了一些麻煩。 這是我的頭文件的一部分:
namespace unstd {
template<typename T,class Allocator = std::allocator<T>>
class SList
{
public:
typedef typename Allocator::value_type value_type;
typedef typename size_t size_type;
typedef typename Allocator::template rebind<T>::other allocator_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef typename T* pointer;
typedef typename const T* const_pointer;
typedef typename ptrdiff_t difference_type;
typedef typename SList_Iterator_Forward<T> iterator;
typedef typename const SList_Iterator_Forward<T> const_iterator;
....
/*----- ITERATORS -------*/
iterator begin();
...
};}
讓我們考慮例如begin()方法。 我在.cpp文件中編寫了以下未編譯的內容:
template<typename T, class Allocator>
iterator SList<T,Allocator>::begin()
{
}
//neither the following compile
template<typename T, class Allocator>
SList<T,Allocator>::iterator SList<T,Allocator>::begin()
{
}
我有幾個問題:
1)
template<typename T, class Allocator>
typename SList<T,Allocator>::iterator SList<T,Allocator>::begin()
^^^^^^^^
這很煩人,但是要習慣它。 編譯器假定所有類似模板的內容都是變量,因此,如果是類型,則必須特別說明。
2)編譯器需要知道函數定義是針對具有兩個模板參數的SList
類的,並且兩者都可以是任何東西,這不是專門知識。 我意識到您的默認值是默認的,如果缺少默認值也不會模棱兩可,但是我認為這主要是為了簡化編譯器。
3)定義可以在單獨的文件中,但不能在其自己的“翻譯單元”中(已編譯的文件.cpp及其包含在內)。 因此,請勿將其放在.cpp文件中,這只會造成混淆。 模板定義位於.incl文件中並不罕見,該文件包含在標題的底部。 這使編譯器感到滿意,並且聲明和定義仍然分開。
有兩個原因:
這是因為丟失SList<T,Allocator>::
在返回類型的前面iterator
的begin
iterator
是一個依賴類型,因此在兩個地方都需要在SList<T, Allocator>::iterator
前面輸入typename
您不會從具有非void
返回類型的函數中返回值; 您需要退貨。
因為名稱是SList<T, Allocator>
,所以您必須告訴編譯器類的全名,因為您需要能夠引用類型名稱Allocator
,並且這就是這樣。
您不能這樣做,因為編譯器要求模板的實現與聲明位於同一文件中(除非您執行顯式實例化,這會削弱模板的通用性)。 因此,您需要最后將實現#include
到接口文件中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.