2012-04-13 66 views
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

+0

也许你的意思是你需要指出迭代器是否需要遍历double? – 2012-04-13 17:18:41

+0

嘿,这可以做到,但它不漂亮。我建议只是在注释中,因为返回类型会强制它至少将迭代器类型转换为“double”。 – 2012-04-13 17:23:17

+0

'double'而不是'int'当然。我纠正了这一点,谢谢。我的“真实世界返回类型”不取决于迭代器... – 2012-04-13 17:59:44

回答

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; 
} 

另一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

如果你不想使用升压/ 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集合实现可以有两个以上的模板参数(第二个是具有默认值的分配器)

+0

stdlib集合具有_at least_两个模板参数,但只要其他参数具有缺省值,它们就可以有更多的参数。也就是说,这个代码是不可移植的。 – ildjarn 2012-04-13 17:20:28