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

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

4

2 回答 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 代替。

于 2012-04-13T17:19:49.220 回答
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());

有点难看,但有效:)

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

于 2012-04-13T17:19:23.770 回答