2015-12-21 90 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但不包含你的代碼的兼容迭代器。