Reputation: 33
I recently had a question when implementing my own Vector container for study purpose.
In my Vector class a non-template member function and a template member function with the same name are declared (insert function). In case of conflict (when some template specialization matches the non-template function signature exactly), compiler gave me error....
Suppose that my vector class has 2 functions called insert:
/* Vec.h */
template <class T> class Vec {
public:
iterator insert ( iterator position, size_type n, const value_type& val );
template <class InputIterator>
iterator insert (iterator position, InputIterator first, InputIterator last);
}
#include "Vec.hpp"
In Vec.hpp:
/* Vec.hpp */
template <class T>
typename Vec<T>::iterator Vec<T>::insert( iterator position,
size_type n,
const value_type& val)
{
/* Implementation */
}
template <class T> template <class InputIterator>
typename Vec<T>::iterator Vec<T>::insert( iterator position,
InputIterator first,
InputIterator last )
{
/* Some code ... */
/* Copy the element */
while( first != last )
{
new ( position + idx ) T(*first);
++idx;
++first;
}
/* Some other code ... */
}
In main.cpp:
int main()
{
Vec<int> myVec;
MyVec.push_back(5);
myVec.insert( myVec.begin(), 3, 3);
}
Compiler error:
../Vec.hpp: In instantiation of ‘T* Vec<T>::insert(Vec<T>::iterator, InputIterator, InputIterator) [with InputIterator = int; T = int;
Vec<T>::iterator = int*]’:
../main.cpp:128:45: required from here
../Vec.hpp:306:30: error: invalid type argument of unary ‘*’ (have ‘int’)
new ( position + idx ) T(*first);
^
It seems like compiler tries to use the template insert function instead of non-template one. This is contradict with what I thought. And it looks like although I did not provide the argument list for insert function:
myVec.insert<int*>
The compiler implicitly instantiate the template insert function with int type.
In member templates from cppreference, it also says that the compiler should use non-template one in this case.(Please refer to Member function templates section)
My environment: Ubuntu 16.04 LTS, g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
Please
explain why the compiler uses template member function
Provide solution to the above issue. so that when I do insert( iterator, int, int) or other similar function calls such as insert( iterator, unsigned int/long, unsigned int/long), it will call the proper member function.
Thanks everyone's help. I really appreciate it!!
Upvotes: 1
Views: 170
Reputation: 275740
myVec.insert( myVec.begin(), 3, 3);
First thing that happens is that it finds all possible overloads:
iterator insert ( iterator position, size_type n, const value_type& val );
template <class InputIterator>
iterator insert (iterator position, InputIterator first, InputIterator last);
then it does template argument deduction. In this case, InputIterator=int
is valid.
iterator insert ( iterator position, size_type n, const int& val );
template <>
iterator insert (iterator position, int first, int last);
as both 3
and 3
are of type int
.
Now it does ocerload resolution. The template function here has zero conversions. The non-template one requires converting int
to size_type
.
The one with zero conversions wins. If they tied, then the non-template function wins on ties; but zero conversion wins.
Note that the iterator type is int
not int*
; this causes the body to fail to compile, because int
cannot be dereferenced.
Upvotes: 3