With C++17 inheriting from std::iterator is deprecated in favour of using iterator traits directly as per for example https://www.fluentcpp.com/2018/05/08/std-iterator-deprecated/
This should be as simple as providing 'using's for each of:
and removing the base class. We've just migrated some legacy code to compile under C++23 (under MSVC on windows) and it would be nice to remove warnings as well. As far as I can tell it already defines the correct operations and does rely on inheriting anything like say operator++ from the base class. However this causes cryptic failures such as:
error C2672: 'std::distance': no matching overloaded function found
I notice that even adding a single type definition for one of the above is enough to break something. Even if I define the traits such that they ought to exactly match the definitions provided via std::iterator. Can anyone explain this?
For example the traits should match the base class if you go for an intermediate step:
template <typename Internal>
class Iterator: public std::iterator<std::forward_iterator_tag, typename std::iterator_traits<Internal>::value_type>
{
using IterType = typename std::iterator<std::forward_iterator_tag, typename std::iterator_traits<Internal>::value_type>;
using iterator_category = typename IterType::iterator_category;
using value_type = typename IterType::value_type;
using difference_type = typename IterType::difference_type;
using pointer = typename IterType::pointer;
using reference = typename IterType::reference;
Even just adding using difference_type
alone breaks code.
I tried a static_assert to see how difference_type was defined and it isn't.
std::iterator_traits<Internal>::difference_type>,
"difference_type mismatch");
But defining it to exactly the same type seems to trigger some dark template voodoo. If I invert the static assertion it fails proving I've defined it correctly.
static_assert(!std::is_same_v<difference_type, typename
std::iterator_traits<Internal>::difference_type>, "difference_type mismatch");
error C2338: static_assert failed: 'difference_type mismatch'
Q What on Earth is going on here?
Note as a workaround we can define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING but it would be nice to deal with the problem properly. For my own education I would like to understand it as well. Unfortunately I cannot post the entire legacy code in question.
Though its a good idea I cannot presently look at the errors in another compiler to get a different perspective (making that possible is on the todo list but quite far down).
References:
Your typedefs are in private
section,
so typename Iterator<SomeType>::value_type
is ill formed at global and std
scopes.
As, std::iterator_traits
is SFINAE friendly, and provides the typedef "automatically" only when all typedefs exist (and are accessible).
So even adding one private expected typedef in non-public section, make std::iterator_traits
empty for that