Home > Mobile >  a C template question: choose the unexpect function
a C template question: choose the unexpect function

Time:12-15

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) {
    // ...
}
  • Related