C++ 模板问题:选择意外函数

a C++ template question: choose the unexpect function

我正在像 std::list 那样写我的列表,所以我有这样的功能:

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

这是主要功能

int main() {
    tinystd::list<int> mylist;
    tinystd::list<int>::iterator it;
    it = mylist.begin();

    // error happens here
    mylist.insert(it, 2, 20);
}

编译器似乎会选择函数 template <typename _InputIter> iterator insert(iterator __pos, _InputIter __begin, _InputIter __end) 并导致错误提示 indirection requires pointer operand ('int' invalid)

我想知道为什么会出现这种情况以及如何修改它。 非常感谢你^^

因为第二个 insert 在重载决议中获胜;给定 mylist.insert(it, 2, 20); 模板参数 _InputIter 可以推断为 int 然后它是一个完全匹配。另一方面,第三个 insert 需要从 intsize_t.

的隐式转换

您可以使用 std::input_iterator (C++20 起)指定 _InputIter 作为输入迭代器必须满足要求。

template <std::input_iterator _InputIter>
iterator insert(iterator __pos, _InputIter __begin, _InputIter __end) {
    // ...
}

在 C++20 之前,您可以对 _InputIter 施加限制,例如必须与 operator*.

一起使用
template <typename _InputIter, std::void_t<decltype(*std::declval<_InputIter>())>* = nullptr>
iterator insert(iterator __pos, _InputIter __begin, _InputIter __end) {
    // ...
}