I am trying to make my own mini-vector class and I am attempting to replicate some of the functions, but I can not get them to behave the same way when passing calls such as begin()
and end()
as parameters - the compiler doesn't deduce the right version. Here is an example:
template<typename T>
class Iterator
{
public:
Iterator() {}
};
template<typename T>
class ConstIterator
{
public:
ConstIterator() {}
};
template <typename T>
class MyList {
public:
MyList() {}
Iterator<T> Begin()
{
return Iterator<T>();
}
ConstIterator<T> Begin() const
{
return Iterator<T>();
}
void Insert(ConstIterator<T> it)
{
}
};
int main() {
MyList<int> myList;
myList.Insert(myList.Begin());
}
At myList.Insert(myList.Begin());
it does not try to use the correct version of Begin()
, the const one.
From what I can tell in the std::vector implementation, there are two versions of begin() - one returns an iterator
and one returns a const_iterator
. The only other difference between them is that one is a const method (the one returning a const_iterator).
_NODISCARD _CONSTEXPR20 iterator begin() noexcept {
auto& _My_data = _Mypair._Myval2;
return iterator(_My_data._Myfirst, _STD addressof(_My_data));
}
_NODISCARD _CONSTEXPR20 const_iterator begin() const noexcept {
auto& _My_data = _Mypair._Myval2;
return const_iterator(_My_data._Myfirst, _STD addressof(_My_data));
}
Many methods, like std::vector::insert take a const_iterator parameter:
_CONSTEXPR20 iterator insert(const_iterator _Where, const _Ty& _Val) { // insert _Val at _Where
return emplace(_Where, _Val);
}
_CONSTEXPR20 iterator insert(const_iterator _Where, _Ty&& _Val) { // insert by moving _Val at _Where
return emplace(_Where, _STD move(_Val));
}
However, there is nothing in the insert method that would make the compiler use the const version of begin(). Which means it has to deduce by the return type alone, but as far as I know that's not possible? How is it achieving it then?
CodePudding user response:
There is no deduction. If myList
is not const
-qualified, then the non-const
version of Begin()
is called for myList.Begin()
. Otherwise the const
version is called. How you use the result of myList.Begin()
is not relevant.
The standard library avoids your issue by providing a conversion from the non-const iterator to the const iterator. For example you could give ConstIterator
a constructor which accepts a Iterator
, which you must have anyway to make the return Iterator<T>();
statement in your const
version of Begin()
work (assuming that is not a typo).