2012-04-13 77 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