Reputation: 313
I have the following two functions defined in an STL-like List Container:
// copy the specified VALUE some COUNT number of times and insert copies
// right before POS.
Iterator insert(Iterator pos, size_type count, const value_type
&value);
// copy the values from [FIRST, LAST) from the specified Iterators and
// place before POS.
template<class InputIt>
Iterator insert(Iterator pos, InputIt first, InputIt last);
I then tried to test my function implementations with some arbitrary code:
std::list<int> stlList = { 1, 2, 3, 4, 5 };
MyList<int> intList;
intList.insert(intList.begin(), 5, 0); // expected call to first insert
intList.insert(intList.begin(), stlList.begin(), stlList.end()); // expected call to second insert
However, for both of them it seems like the second function is being called. I kind of see the ambiguity, since both functions have three parameters, I see how the compiler may call the wrong function. But I'm not really sure what I am missing. I have been basing my functions off of STL and as far as I can tell, they defined them in nearly the same way (STL's List Insert).
Upvotes: 1
Views: 483
Reputation: 118352
template<class InputIt>
Iterator insert(Iterator pos, InputIt first, InputIt last);
This template defines a function whose second and third parameters are the same type. You are assuming in your head that the second and the third parameters must be iterators. But there is no such requirement here, only that the second and the third parameter's type must be the same. The name of the template parameter, "InputIt", is irrelevant.
intList.insert(intList.begin(), 5, 0); // expected call to first insert
The second and the third parameter to this function call is the same type: an int
. The other candidate for the overload resolution:
Iterator insert(Iterator pos, size_type count, const value_type
&value);
This one has different types for the second and third parameters. Although both ints can be converted here, the other template function is the better match, hence it gets selected.
Upvotes: 2
Reputation: 180720
The reason intList.insert(intList.begin(), 5, 0);
choses
template<class InputIt>
Iterator insert(Iterator pos, InputIt first, InputIt last);
over
Iterator insert(Iterator pos, size_type count, const value_type &value);
Is because the template function produces an exact match.
5
and 0
have the same type so InputIt
gets deduced as int
which makes the function look like
Iterator insert(Iterator pos, int first, int last);
Where your other overload looks like
Iterator insert(Iterator pos, size_t first, int last);
As you can see no conversion is required to call the template deduced version so it is preferred over the non template overload.
You would have to cast 5
to a size_t
to get it to call the non template overload or use SFINAE to only call the template overload when InputIt
is really an iterator.
Upvotes: 2