I am writing my list like the std::list so I have functions like this:
template <typename _Tp>
class list {
public:
// ...
iterator insert(iterator __pos, const _Tp &__val) {
// ...
}
template <typename _InputIter>
iterator insert(iterator __pos, _InputIter __begin, _InputIter __end) {
if (__begin == __end) return __pos;
// here I use the *__begin... so ...
iterator __ret = insert(__pos, *__begin);
while ( __begin != __end) insert(__pos, *__begin);
return __ret;
}
iterator insert(iterator __pos, size_t __cnt, const _Tp &__val) {
// ...
}
}
this is the main function
int main() {
tinystd::list<int> mylist;
tinystd::list<int>::iterator it;
it = mylist.begin();
// error happens here
mylist.insert(it, 2, 20);
}
It seems like the compiler will choose the function template <typename _InputIter> iterator insert(iterator __pos, _InputIter __begin, _InputIter __end)
and cause an error says that indirection requires pointer operand ('int' invalid)
I want to know why this happens and how to modify it. Thank U so much ^^
CodePudding user response:
Because the 2nd insert
wins in overload resolution; given mylist.insert(it, 2, 20);
the template parameter _InputIter
could be deduced as int
and then it's an exact match. On the other hand, the 3rd insert
requires an implicit conversion from int
to size_t
.
You can use std::input_iterator
(since C 20) to specify that _InputIter
must satisfy the requirements as an input iterator.
template <std::input_iterator _InputIter>
iterator insert(iterator __pos, _InputIter __begin, _InputIter __end) {
// ...
}
Before C 20 you can impose restrictions on _InputIter
, e.g. must be usable with operator*
.
template <typename _InputIter, std::void_t<decltype(*std::declval<_InputIter>())>* = nullptr>
iterator insert(iterator __pos, _InputIter __begin, _InputIter __end) {
// ...
}