传递迭代器而不是容器

Pass iterator instead of container

本文关键字:迭代器      更新时间:2023-10-16

目前,我坚持使用一些代码,例如fooA()(不介意正文),它需要一个特定的容器,比如vector<double>,作为参数。

double fooA(std::vector<double> const& list)
{
    return list[0];
}

现在,我想泛化并使用迭代器:

template<typename InputIterator>
double fooB(InputIterator first, InputIterator last)
{
    return *first;
}

如何声明fooB()需要迭代器迭代double

有人可能会通过vector<string>::iterator,或者更糟糕的是,它可能在没有警告的情况下编译,vector<int>::iterator

对于 C++03:

#include <iterator>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/utility/enable_if.hpp>
template<typename InputIterator>
typename boost::enable_if<
    boost::is_same<
        typename boost::remove_cv<
            typename std::iterator_traits<InputIterator>::value_type
        >::type,
        double // expected value_type
    >,
    double     // fooB return type
>::type
fooB(InputIterator first, InputIterator last)
{
    return *first;
}

另一个不使用 Boost 的 C++03 解决方案,但在传递无效类型时可能会产生更丑陋的错误:

#include <iterator>
void fooB_helper(double) { }
template<typename T> void fooB_helper(T const&);
template<typename InputIterator>
double fooB(InputIterator first, InputIterator last)
{
    fooB_helper(typename std::iterator_traits<InputIterator>::value_type());
    return *first;
}

对于C++11,您可以使用表达式SFINAE而不是enable_if,也可以使用static_assert而不是SFINAE。

如果您不想使用 Boost/C++11,则可以使用此方法:

template<typename B, template<typename A1, typename B1> class Container>
double fooB(typename Container<int, B>::iterator first,
   typename Container<int, B>::iterator last)
{
  return 0;
}

要调用:

vector<int> a;
fooB<vector<int>::allocator_type, vector>(a.begin(), a.end());

有点丑,但工作:)

另外:不可移植,因为 std 集合实现可以有两个以上的模板参数(第二个是具有默认值的分配器)