C ++中Deduce类型的模板类型

时间:2015-12-21 11:11:02

标签: c++ c++11

为“迭代器”范围编写通用函数时,我通常会这样做:

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吗?

2 个答案:

答案 0 :(得分:22)

第二个是最惯用的。

  • 第一个不适用于代理(std :: vector&lt; bool&gt;)
  • 第三个不适用于指针。

答案 1 :(得分: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而不是你的代码。