I suspect the prototypes of fill constructor and range constructor of std::vector (and many other STL types) given in this webpage are not right, so I implement a NaiveVector to mimic these two prototypes.
My code is:
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
struct NaiveVector {
vector<T> v;
NaiveVector(size_t num, const T &val) : v(num, val) { // fill
cout << "(int num, const T &val)" << endl;
}
template <typename InputIterator>
NaiveVector(InputIterator first, InputIterator last) : v(first, last) { // range
cout << "(InputIterator first, InputIterator last)" << endl;
}
size_t size() const { return v.size(); }
};
int main() {
NaiveVector<int> myVec1(5,1); // A
cout << "size = " << myVec1.size() << endl;
for (auto n : myVec1.v) { cout << n << " "; }
cout << endl;
cout << "-----" << endl;
vector<int> vec({1,2,3,4,5});
NaiveVector<int> myVec2(vec.begin(), vec.end());// B
cout << "size = " << myVec2.size() << endl;
for (auto n : myVec2.v) { cout << n << " "; }
cout << endl;
}
And the output is:
$ g++ overload.cc -o overload -std=c++11
$ ./overload
(InputIterator first, InputIterator last) // should be: (int num, const T &val)
size = 5
1 1 1 1 1
-----
(InputIterator first, InputIterator last)
size = 5
1 2 3 4 5
As I suspected from the beginning, the compiler cannot differentiate the two constructors properly. Then my question is: how does std::vector's fill constructor and range constructor differentiate from each other?
Rephrase: how to implement the two constructors of this NaiveVector?
This question seems to be a duplicate of this question but the answer is not satisfying. Additionally, C++11 itself doesn't provide a is_iterator<>.. (MSVC has lots of hacks).
Edit: it is allowed to bind an rvalue to a constant lvalue reference, so the first constructor of NaiveVector is valid for A.
C++03
[lib.sequence.reqmts]/9
For every sequence defined in this clause and in clause 21:
the constructor
template <class InputIterator>
X(InputIterator f, InputIterator l, const Allocator& a = Allocator())
shall have the same effect as:
X(static_cast<typename X::size_type>(f),
static_cast<typename X::value_type>(l),
a)
if InputIterator is an integral type.
...
[lib.sequence.reqmts]/11
One way that sequence implementors can satisfy this requirement is to specialize the member template for
every integral type. Less cumbersome implementation techniques also exist.
In other words, the standard says that if the range constructor gets selected by overload resolution but the "iterator" type is actually an integral type, it has to delegate to the fill constructor by casting its argument types to force the latter to be an exact match.
C++11/C++14
[sequence.reqmts]/14
For every sequence container defined in this clause and in clause 21:
If the constructor
template <class InputIterator>
X(InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type())
is called with a type InputIterator that does not qualify as an input iterator, then the constructor shall not participate in overload resolution.
...
[sequence.reqmts]/15
The extent to which an implementation determines that a type cannot be an input iterator is unspecified,
except that as a minimum integral types shall not qualify as input iterators.
This is more or less the way the standard hints to you to use SFINAE (which works reliably in C++11 as opposed to C++03).
C++17
The wording is similar, except that the paragraph about integral types not being iterators has been moved to [container.requirements.general]/17.
Conclusion
You can write your range constructor to look something like this:
template <typename InputIterator,
typename = std::enable_if<is_likely_iterator<InputIterator>>::type>
NaiveVector(InputIterator first, InputIterator last)
The is_iterator helper template might simply disqualify integral types and accept all other types, or it might do something more sophisticated such as checking whether there is an std::iterator_traits specialization that indicates that the type is an input iterator (or stricter). See libstdc++ source, libc++ source
Both approaches are consistent with the standard's mandated behaviour of std::vector in C++11 and later. The latter approach is recommended (and will be consistent with what the real std::vector is likely to do on typical implementations), because if you pass arguments that are implicitly convertible to the types expected by the fill constructor, you would hope that the class would "do the right thing" and not select the range constructor only to have it fail to compile. (Although I suspect this is fairly uncommon.) Relative to the C++03 std::vector, it is a "conforming extension" since in that case the constructor call would not compile.
If you read the documentation at http://en.cppreference.com/w/cpp/container/vector/vector carefully, you will notice the following (emphasis mine):
4) Constructs the container with the contents of the range [first, last).
This constructor has the same effect as vector(static_cast<size_type>(first), static_cast<value_type>(last), a) if InputIt is an integral type. (until C++11)
This overload only participates in overload resolution if InputIt satisfies InputIterator, to avoid ambiguity with the overload (2).
The confusion is not with the std::vector but your expectation of which of your constructors gets called. Your code doesn't have the checks to make sure that the second constructor gets called only if the above condition of std::vector is met.
In your case, when you use
NaiveVector<int> myVec1(5,1);
the second constructor can be called by using int as the template parameter without requiring any conversion. The compiler needs to convert an int to a size_t in order to be able to call the first constructor. Hence, the second constructor is a better fit.
You can try adding some type trait check to verify that arguments of second constructor are iterators over T elements:
template
<
typename InputIterator
, typename = typename ::std::enable_if
<
::std::is_same
<
T &
, typename ::std::remove_const
<
decltype(*(::std::declval< InputIterator >()))
>::type
>::value
, void
>::type
>
NaiveVector(InputIterator first, InputIterator last) : v(first, last)
{
cout << "(InputIterator first, InputIterator last)" << endl;
}
Run this code online
Related
Please take a look at the std::advance function.
According to cppreference the complexity is:
Linear.
However, if InputIt additionally meets the requirements of RandomAccessIterator, complexity is constant.
So if I pass an iterator and an integer, how does the program deduce what iterator it is and how it is implemented? So are there 2 overloads for the function or what?
how program deduce what iterator it and how it is implemented?
It uses std::iterator_traits<T>::iterator_category to determine iterator category and then does tag dispatching.
std::iterator_traits is specialised for raw pointers. Raw pointers are random-access iterators.
E.g.:
template<class I>
void doadvance(I& i, size_t n, std::random_access_iterator_tag) {
i += n;
}
template<class I, class Tag>
void doadvance(I& i, size_t n, Tag) {
while(n--)
++i;
}
template<class I>
void advance(I& i, size_t n) {
using Tag = typename std::iterator_traits<I>::iterator_category;
doadvance(i, n, Tag{});
}
In C++17 instead of tag dispatching it can use if constexpr, but that would make the standard library not backward compatible. This is why it has to keep using tag dispatching.
IMO, std::next has a better interface than std::advance because it returns the iterator, so that the invocation does not have to occupy its own line of code.
how program deduce what iterator it is
std::iterator_traits is used, i.e. std::iterator_traits<It>::iterator_category will be checked, and if it's std::random_access_iterator_tag, means it's a RandomAccessIterator.
BTW: std::iterator_traits is specialized for raw pointers; they're always RandomAccessIterator.
So are there 2 overloads for the function or what?
There're no more overloads of std::advance, the implementation usually implements several helper function overloads, which are called according to the iterator_category in std::advance.
I am making some sort of container and I would like to mimic the interface of an std::vector. However, I am having a hard time understanding how the constructor overload (4) works. The problem is that it normally conflicts with overload (2).
// (2)
vector(size_type count, const T& value, const Allocator& alloc = Allocator());
// (4)
template<class InputIt>
vector(InputIt first, InputIt last, const Allocator& alloc = Allocator());
According to cppreference, until C++11 :
this constructor has the same effect as overload (2) if InputIt is an integral type.
I understand how it was done (tag dispatching or template specialization, I suppose), but I have no idea how the new behavior is achieved in C++11 :
This overload only participates in overload resolution if InputIt satisfies InputIterator, to avoid ambiguity with the overload (2).
Is that some sort of SFINAE trick ? I do not understand how SFINAE could work here. And, since concepts or not a thing in C++11 (nor C++14), I have no idea about how I could do that for my container.
Hence my question : how is it done in the standard library (or at least a guess), and how can I do it relatively easily for my container ?
The way it's currently worded in the standard is rather interesting. [sequence.reqmts]/p15:
The extent to which an implementation determines that a type cannot be
an input iterator is unspecified, except that as a minimum integral
types shall not qualify as input iterators.
In other words, it's sufficient for implementations to test for integral types only, but they can do more if they want to.
With a SFINAE-friendly std::iterator_traits (voted into the C++17 working paper as an LWG issue, but probably provided by most implementations all along anyway), for example, one might test that std::iterator_traits<InputIterator>::iterator_category is valid and denotes a type derived from std::input_iterator_tag with something like
template<class InputIt, std::enable_if_t<std::is_base_of<std::input_iterator_tag,
typename std::iterator_traits<InputIterator>::iterator_category>::value, int> = 0>
vector(InputIt first, InputIt last, const Allocator& alloc = Allocator());
Note that this is just a proof-of-concept. Real implementations in standard libraries would probably be 1) more complex (for example, it may optimize based on iterator category - for forward iterators or better, it can allocate memory for all the elements in one go) and 2) even uglier than this and filled with underscores to avoid name conflicts.
I got very weird problem
for code like this
template <typename T>
struct A{
explicit A(unsigned int size = 0, const T &t = T())
{
}
template <typename InputIterator>
A(InputIterator first, InputIterator last) {
for(;first != last ; ++first)
{
*first; //do something with iterator
}
}
};
when I for example define
A<int> a(10,10);
the second constructor for iterators is used instead of first one.
How then vectors constructors work, when they looks preety the same?
explicit vector (size_type n, const value_type& val = value_type(),
const allocator_type& alloc = allocator_type());
template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
And I can make vector v(10,10) without having any troubles.
PS I got error like this
temp.cpp: In instantiation of ‘A<T>::A(InputIterator, InputIterator) [with = int; T = int]’:
temp.cpp:17:15: required from here
temp.cpp:12:4: error: invalid type argument of unary ‘*’ (have ‘int’)
The reason the compiler chooses the second constructor in case of your A is simple: your 10 is a value of signed type int, while size_type is some unsigned integer type. This means that 10 has to be converted to that unsigned integer type. The need for that conversion is what makes the first constructor to lose the overload resolution to the second constructor (which is an exact match for InputIterator = int). You can work around this problem by doing
A<int> a(10u, 10);
This eliminates the need for int -> unsigned conversion and makes the first constructor win the overload resolution through "non-template is better than template" clause.
Meanwhile, the reason it works differently with std::vector is that the language specification gives special treatment to the constructors of standard sequences. It simply requires that std::vector constructor invocation with two integers of the same type as arguments is somehow "magically" resolved to the first constructor from your quote (i.e. the size-and-initializer constructor). How each specific implementation achieves that is up to the implementation. It can overload the constructor for all integer types. It can use a functionality similar to enable_if. It can even hardcode it into the compiler itself. And so on.
This is how it is stated in C++03, for example
23.1.1 Sequences
9 For every sequence defined in this clause and in clause 21:
— the constructor
template <class InputIterator>
X(InputIterator f, InputIterator l, const Allocator& a = Allocator())
shall have the same effect as:
X(static_cast<typename X::size_type>(f),
static_cast<typename X::value_type>(l), a)
if InputIterator is an integral type
C++11, takes it even further by approaching it from a different angle, although the intent remains the same: it states that if InputIterator does not qualify as input iterator, then the template constructor should be excluded from overload resolution.
So, if you want your class template A to behave the same way std::vector does, you have to deliberately design it that way. You can actually take a peek into the standard library implementation on your platform to see how they do it for std::vector.
Anyway, a low-tech brute-force solution would be to add a dedicated overloaded constructor for int argument
explicit A(unsigned int size = 0, const T &t = T())
{ ... }
explicit A(int size = 0, const T &t = T())
{ ... }
That might, of course, imply that you'll eventually have to add overloads for all integer types.
A better solution, which I already mentioned above, would be to disable the template constructor for integer arguments by using enable_if or similar SFINAE-based technique. For example
template <typename InputIterator>
A(InputIterator first, InputIterator last,
typename std::enable_if<!std::is_integral<InputIterator>::value>::type* = 0)
Do you have C++11 features available to you in your compiler?
When InputIterator isint, the instantiated
A(int first, int last)
is a better match than the instantiated
explicit A(unsigned int size = 0, const int &t = int())
due to the first argument being unsigned. A<int> a((unsigned int)10,10) should call the constructor you expect. You can also use SFINAE to prevent a match unless the constructor really is being passed two iterators to T:
#include <iostream>
using namespace std;
template <typename T>
struct A{
explicit A(unsigned int size = 0, const T &t = T())
{
cout << "size constructor for struct A" << endl;
}
template <class I>
using is_T_iterator = typename enable_if<is_same<typename iterator_traits<I>::value_type, T>::value, T>::type;
template <typename InputIterator>
A(InputIterator first, InputIterator last, is_T_iterator<InputIterator> = 0) {
cout << "iterator constructor for struct A" << endl;
for(;first != last ; ++first)
{
*first; //do something with iterator
}
}
};
int main()
{
A<int>(10,10);
A<int>((int*)0,(int*)0);
//A<int>((char*)0,(char*)0); //<-- would cause compile time error since (char *) doesn't dereference to int
return 0;
}
If the condition that both arguments are iterators to T is too strict, there are looser formulations. For instance, you can guarantee that both arguments are iterators. You could go further (but not quite as far as the example above) and ensure that they "point" to a type that is convertible to T (using std::is_convertible).
That is correct, the templated thing is a better match, so it is selected. The standard library implementation fight hard to steer for a sensible behavior with all the templated members. You may want to look up some implementation code for specializations, if you want to implement a similar collection of your own.
Or you may find a way to dodge the problem.
There was a fine GOTW article with all the cases of function overload selection and some advice to fight it.
Your first argument in A<int>(10, 10) doesn't match your explicit constructor because 10 is signed, so it's using the templatized constructor instead. change it to A<int>(10u, 10) and you may end up with the results you expect.
If you're writing a general library, you may want to make the
extra effort, and use template meta programming to catch all of
the cases. Or simply provide explicit overloads for all of the
integral types. For less generic use, it is usually sufficient
to follow the rule that anytime you provide an overload for any
integral type, you also provide one for int (so you would have
a constructor A::A( int size, T const& initialValue = T() ),
in addition to the ones you already provide).
More generally: you should probably just make the size an
int, and be done with it. The standard library is caught up
in a lot of historical issues, and must use size_t by default,
but in general, unless there is a very strong reason to do
otherwise, the normal integral type in C++ is int; in
addition, the unsigned types in C++ have very strange semantics,
and should be avoided anytime there is any chance of arithmetic
operations occuring.
I am practicing C++ by building my own version of vector, named "Vector". I have two constructors among others, fill constructor and range constructor. Their declarations look like following:
template <typename Type>
class Vector {
public:
// fill constructor
Vector(size_t num, const Type& cont);
// range constructor
template<typename InputIterator> Vector(InputIterator first, InputIterator last);
/*
other members
......
*/
}
The fill constructor fills the container with num of val; and the range constructor copies every value in the range [first, last) into the container. They are supposed to be the same with the two constructors of the STL vector.
Their definitions goes following:
//fill constructor
template <typename Type>
Vector<Type>::Vector(size_t num, const Type& cont){
content = new Type[num];
for (int i = 0; i < num; i ++)
content[i] = cont;
contentSize = contentCapacity = num;
}
// range constructor
template <typename Type>
template<typename InputIterator>
Vector<Type>::Vector(InputIterator first, InputIterator last){
this->content = new Type[last - first];
int i = 0;
for (InputIterator iitr = first; iitr != last; iitr ++, i ++)
*(content + i) = *iitr;
this->contentSize = this->contentCapacity = i;
}
However, when I try to use them, I have problem distinguishing them.
For example:
Vector<int> v1(3, 5);
With the this line of code, I intended to create a Vector that contains three elements, each of which is 5. But the compiler goes for the range constructor, treating both "3" and "5" as instances of the "InputIterator", which, with no surprises, causes error.
Of course, if I change the code to:
Vector<int> v1(size_t(3), 5);
Everything is fine, the fill constructor is called. But that is obviously not intuitive and user friendly.
So, is there a way that I can use the fill constructor intuitively?
You can use std::enable_if (or boost::enable_if if you don't use C++11) to disambiguate the constructors.
#include <iostream>
#include <type_traits>
#include <vector>
using namespace std;
template <typename Type>
class Vector {
public:
// fill constructor
Vector(size_t num, const Type& cont)
{
cout << "Fill constructor" << endl;
}
// range constructor
template<typename InputIterator> Vector(InputIterator first, InputIterator last,
typename std::enable_if<!std::is_integral<InputIterator>::value>::type* = 0)
{
cout << "Range constructor" << endl;
}
};
int main()
{
Vector<int> v1(3, 5);
std::vector<int> v2(3, 5);
Vector<int> v3(v2.begin(), v2.end());
}
The above program should first call the fill constructor by checking if the type is an integral type (and thus not an iterator.)
By the way, in your implementation of the range constructor, you should use std::distance(first, last) rather than last - first. Explicitly using the - operator on iterators limits you to RandomAccessIterator types, but you want to support InputIterator which is the most generic type of Iterator.
Even std::vector seems to have this issue.
std::vector<int> v2(2,3);
chooses
template<class _Iter>
vector(_Iter _First, _Iter _Last)
In Visual C++, even though it should match closer to the non templated case..
Edit: That above function (correctly) delegates the construction to the below one. I am totally lost..
template<class _Iter>
void _Construct(_Iter _Count, _Iter _Val, _Int_iterator_tag)
Edit #2 AH!:
Somehow this below function identifies which version of the constructor is meant to be called.
template<class _Iter> inline
typename iterator_traits<_Iter>::iterator_category
_Iter_cat(const _Iter&)
{ // return category from iterator argument
typename iterator_traits<_Iter>::iterator_category _Cat;
return (_Cat);
}
The above shown _Construct function has (atleast) 2 versions overloading on the third variable which is a tag to returned by the above _Iter_cat function. Based on the type of this category the correct overload of the _Construct is picked.
Final edit:
iterator_traits<_Iter> is a class that seems to be templated for many different common varieties, each returning the appropriate "Category" type
Solution: It appears template specialization of the first arguement's type is how the std library handles this messy situation (primitive value type) in the case of MS VC++. Perhaps you could look into it and follow suit?
The problem arises (I think) because with primitive value types, the Type and size_t variables are similar, and so the template version with two identical types gets picked.
The problem is the same at the one faced by the standard library implementation. There are several ways to solve it.
You can meticulously provide non-template overloaded constructors for all integral types (in place of the first parameter).
You can use SFINAE-based technique (like enable_if) to make sure the range constructor is not selected for integer argument.
You can branch the range constructor at run-time (by using if) after detecting integral argument (by using is_integral) and redirect control to the proper constructing code. The branching condition will be a compile-time value, meaning that the code will probably be reduced at compile-time by the compiler.
You can simply peek into your version of standard library implementation and see how they do it (although their approach is not required to be portable and/or valid from the point of view of abstract C++ language).
This ambiguity caused problems for early library implementers. It's called the "Do The Right Thing" effect. As far as I know, you need SFINAE to solve it… it might have been one of the first applications of that technique. (Some compilers cheated and hacked their overload resolution internals, until the solution was found within the core language.)
The standard specification of this issue is one of the key differences between C++98 and C++03. From C++11, §23.2.3:
14 For every sequence container defined in this Clause and in Clause 21:
— If the constructor
template <class InputIterator>
X(InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type())
is called with a type InputIterator that does not qualify as an input iterator, then the constructor shall not participate in overload resolution.
15 The extent to which an implementation determines that a type cannot be an input iterator is unspecified, except that as a minimum integral types shall not qualify as input iterators.
For an exercise for my C++ class (which hasn't covered Boost yet), I am having trouble writing a templated method to accept two iterators for summing numeric values in an STL container.
Consider the following example:
#include <iostream>
#include <iterator>
#include <vector>
template<typename T>
double Sum(const T & c) {
return 42.0; // implementation stubbed
}
// need help writing this method signature to accept two iterators
template<typename T>
double Sum(const typename T::const_iterator & begin,
const typename T::const_iterator & end) {
return 43.0; // another implementation stub
}
int main() {
std::vector<double> v;
v.push_back(3.14);
v.push_back(2.71);
v.push_back(1.61); // sums to 7.46
std::cout << Sum(v) << ' ' // line 23
<< Sum(v.begin(), v.end()) // line 24
<< '\n';
}
I expect this code to output 42 43, but it fails to compile.
The error g++ gives me is:
test_exercise2.cpp: In function ‘int main()’:
test_exercise2.cpp:24: error: no matching function for call to ‘Sum(__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >)’
If I comment out line 24, I get 42 as the output, as expected.
I get the same error message whether or not the second templated method is present or not, so for some reason, it's not able to resolve the call on line 24 to the second method I wrote.
What signature must I have for the method that accepts two iterators?
The reason why I'm stuck on this is because I need to support summing over the second element of std::map<K, V>. This will require two more overloads to call ->second instead of dereferencing the iterator:
1. template<typename K, typename V> double Sum(const std::map<K, V> & m); (I'm okay with this one)
2. and another one involving iterators over the map.
I feel like I'll be able to write the methods for std::map if I can figure out how to specify the passing of iterators for std::list and std::map. I'm okay with solutions that use template-templates.
EDIT: The precise wording of problem (omitting non-contributory sentences).
The containers from "the previous exercise" were std::vector<double>, std::list<double>, std::map<std::string, double>.
Create a template function called Sum() that accepts the template
argument T as input and returns a double. The template argument will
be a container.
In the implementation get an iterator (T::const_iterator) for the end. Then create a loop that iterates the container T and adds all
values. Finally return the sum.
In the main program, call the Sum() function for the different container from the previous exercise.
The Sum() function created calculates the sum of the complete
container. Also create a Sum() function that calculates the sum
between two iterators. The function then uses the template argument
for the iterator type and accepts two iterators, the start and end
iterator.
You're overcomplicating this. You want a pair of iterators of any type? Well, that's just as simple as .. two arguments, of any type.
template<typename Iterator>
double Sum(const Iterator& begin,
const Iterator& end) {
return 43.0; // another implementation stub
}
Problem solved.
By the way, take a hint from the C++ Standard lib: If you can't de-reference the iterator, make the user provide a function to get the value from the iterator. Don't special-case std::map because tomorrow there's std::unordered_map and the day after that boost::multimap and all sorts of fun. And what if I wanted you to sum the keys from the std::map, not the values?
Your hardcoded case is a little more complex. A pair of iterators that have to come from std::map? Not even sure if possible without explicit template arguments.
template<typename K, typename V, typename Comp, typename Alloc>
double Sum(
const std::map<K, V, Comp, Alloc>& map
) { ... }
Notice that I specifically said it had to be a std::map instantiation. This allows the compiler to deduce the parameters. From here, you can access the iterators.
As DeadMG said, the simple way is to template on the type of the iterator. The common convention is, on the other hand, to pass iterators by value:
template <typename Iterator>
double Sum( Iterator begin, Iterator end );
As to why the original code was not working, the problem is that the type of the container is not deducible:
template <typename T>
double Sum( T::const_iterator begin, T::const_iterator end );
Sum( v.begin(), v.end() ); // [*] Assume v == const std::vector<double>&
When the compiler tries to infer the type of the arguments to Sum it only sees the type returned by v.begin() and v.end(), which are the iterator. From that type, it cannot guess the type of the container. To be able to determine what the type T is, it would have to test all non template types, and generate all infinite possible instantiations of template types to look whether they have a nested type const_iterator that matches the type of v.begin() and v.end(). Because that would be impossible, to achieve, the language forbids it in the first place.
Beyond that, and related to the comment [*], even if the type would be deducible, overload resolution is performed on the arguments to the function, and not how the expression is later use. In your program, the argument to .begin() is a std::vector<double> non-const lvalue. Because it is not const, the overload selected will yield a non-const iterator (even if in the function you want to call, there is no need to read it).
The distinguishing feature when contrasting iterators from e.g. std::list with iterators from std::map is that the latter have a pair type as their value_type. That is to say, given std::map<K, V> then both std::map<K, V>::value_type and std::iterator_traits<std::map<K, V>::iterator>::value_type are std::pair<const K, V>.
Hence I suggest your Sum template accept any iterator, but that it operates not on elements given from the iterator (i.e. *it) and instead on a 'view': element(*it). Now you can take care to make sure that element 'does the right thing' when faced with a pair.
As a hint, you could declare Sum as the following (with a bit of metaprogramming for getting the return type correctly):
namespace result_of {
// Second template parameter is an implementation detail
template<
typename Iterator
, typename ValueType = typename std::iterator_traits<Iterator>::value_type
>
struct Sum {
// general case: sum over the value type directly
typedef ValueType type;
};
// If an iterator admits an std::pair as its value_type then we end up here
template<typename Iterator, typename Key, typename Value>
struct Sum<Iterator, std::pair<Key, Value> > {
// special case: sum over the second type of the value
typedef Value type;
};
} // result_of
template<typename Iterator>
typename result_of::Sum<Iterator>::type Sum(Iterator begin, Iterator end);