2015-12-21 61 views
17

当写作“迭代”通用功能范围,我通常做的:推断类型的模板键入C++

template <typename Iter> auto func(Iter &first, Iter &last) 
{ 
    using IterType = typename std::decay<decltype(*first)>::type; 
    ... 
} 

另一种方式似乎是:

template <typename Iter> auto func(Iter &first, Iter &last) 
{ 
    using IterType = typename std::iterator_traits<Iter>::value_type; 
    ... 
} 

然而第三:

template <typename Iter> auto func(Iter &first, Iter &last) 
{ 
    using IterType = typename Iter::value_type; 
    ... 
} 

没有申请iterator_traits

从理论上讲,我的函数应该只接收迭代器,如firstlast,第二种形式理想地(imho)是最常用的方式来获得类型。但是使用typename std::decay<decltype(*first)>::type这个最通用的习惯用法是为了不对Iter施加限制,比如定义了一个value_type

+6

我认为这是按地理价值传递迭代器。 – Lingxi

+4

如果'iterator_traits'对某些东西不起作用,则说某事不是迭代器。 –

回答

22

第二个是最习惯的。

  • 第一不与代理(标准::矢量<布尔>)
  • 第三工作不与指针运行。
10

这些都不是很习惯;你应该通过值传递迭代器,而不是通过引用。以下是gcc 4.9中for_each的签名:

template<typename _InputIterator, typename _Function> 
_Function 
for_each(_InputIterator __first, _InputIterator __last, _Function __f) 

正如您所看到的,它是按值传递的。您的功能将不会在习惯用法工作:

func(v.begin(), v.end()); // error, binding non-const ref to rvalue! 

而且,经历iterator_traits不仅仅是惯用的多,它的基本要求。就STL而言,这样的typedef完全是通过iterator_traits定义的:http://en.cppreference.com/w/cpp/concept/ForwardIterator。 iterator_traits为通用事件提供了合理的默认值,但它可以是专用的(就像指针一样)来做不同的事情。不通过iterator_traits基本上意味着有人可以编写一个兼容STL但不包含你的代码的兼容迭代器。