[英]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.