传递迭代器而不是容器

4

目前我遇到了一些类似 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


也许你的意思是需要指示迭代器必须迭代双精度数? - Ivaylo Strandjev
嘿,这是可以做到的,但不太美观。我建议只是放一个注释,因为返回类型将强制迭代器类型至少转换为“double”。 - Mooing Duck
double 而不是 int,当然。我已经更正了,谢谢。我的“真实返回类型”不取决于迭代器... - Julian Prclôs
2个回答

4

对于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。


0

如果您不想使用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());

有点丑,但是可以用 :)

另外:由于标准库中的集合实现可能有两个以上的模板参数(第二个参数是带有默认值的分配器),所以不可移植。


标准库集合至少有两个模板参数,但只要额外的参数具有默认值,它们就可以拥有更多。也就是说,这段代码不可移植。 - ildjarn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接