Containers are required to provide an iterator
type which is implicitly convertible to a const_iterator
. Given this, I am trying to use auto
Why does auto deduce a typ[e in this case that is not convertible to const_iterator?
begin()
:Signatures:
iterator begin();
const_iterator begin() const;
You declared your vector as Packets test (100);
, which is non const.
If you declare it const, auto
type deduction will have the second begin()
overload as a best (and unique) match.
It compiles and run with this simple fix.
Your problem can be reduced to the following example, which fails for the same reasons.
#include <vector>
#include <iterator>
int main()
{
std::vector<int> v;
std::vector<int>::const_iterator it1 = v.begin();
auto it2 = v.end();
auto n = std::distance(it1, it2);
}
std::distance is defined using the same template parameter type for both arguments, and template argument deduction is failing because you have a const_iterator
and iterator
.
User defined conversions are not considered when deducing template arguments from function calls, and since the two arguments have different types in this case, and both are participating in template argument deduction, the deduction fails.
§14.8.1/6 [temp.arg.explicit]
Implicit conversions (Clause 4) will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter type contains no template-parameters that participate in template argument deduction.
§14.8.2.1/4 [temp.over]
...
[ Note: as specified in 14.8.1, implicit conversions will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter contains no template-parameters that participate in template argument deduction. Such conversions are also allowed, in addition to the ones described in the preceding list. —end note ]
You'll need to convert the iterator
to const_iterator
, or specify the template argument to std::distance
explicitly.
auto n = std::distance(it1, static_cast<decltype(it1)>(it2));
or
auto n = std::distance<decltype(it1)>(it1, it2);
Other options are, of course, to not use auto
and explicitly specify the iterator type in both cases, or use the vector::cbegin()
and vector::cend()
member functions when you need to ensure that the type is a const_iterator
.
The problem has nothing common with the iterator conversion. The compiler simply unable to determine the template argument. It is the same if you would write
int x = 10;
long y = 20;
std::cout << std::max( x, y ) << std::endl;
though an object of type int
can be implicitly converted to an object of type long
.
As for your example you could write
const size_t n = std::distance<std::vector<char>::const_iterator> (it, itr);