Thanks to visit codestin.com
Credit goes to github.com

Skip to content

<iterator>: checked_array_iterator/unchecked_array_iterator should have conversions #943

@AlexGuteniev

Description

@AlexGuteniev

Describe the bug
The non-Standard extensions stdext::checked_array_iterator and stdext::unchecked_array_iterator don't participate in constness conversions like modern iterators do:

STL/stl/inc/iterator

Lines 521 to 523 in 5ef22f2

template <class _Ptr>
class checked_array_iterator { // wrap a pointer with checking
static_assert(_STD is_pointer_v<_Ptr>, "checked_array_iterator requires pointers");

STL/stl/inc/iterator

Lines 718 to 720 in 5ef22f2

template <class _Ptr>
class unchecked_array_iterator { // wrap a pointer without checking, to silence warnings
static_assert(_STD is_pointer_v<_Ptr>, "unchecked_array_iterator requires pointers");

Command-line test case

C:\Temp>type meow.cpp
#include <array>
#include <iostream>
#include <iterator>
#include <type_traits>
using namespace std;
using stdext::checked_array_iterator;
using stdext::unchecked_array_iterator;

#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)

template <typename From, typename To>
void verify_convertible() {
    STATIC_ASSERT(is_convertible_v<From, To>);
    STATIC_ASSERT(is_constructible_v<To, From>);
    STATIC_ASSERT(is_assignable_v<To&, From>);
}

template <typename From, typename To>
void verify_NOT_convertible() {
    STATIC_ASSERT(!is_convertible_v<From, To>);
    STATIC_ASSERT(!is_constructible_v<To, From>);
    STATIC_ASSERT(!is_assignable_v<To&, From>);
}

struct Base {};
struct Derived : Base {};

int main() {
    array<int, 5> arr{{10, 20, 30, 40, 50}};

    {
        array<int, 5>::iterator standard_iter = arr.begin();
        standard_iter += 1;
        cout << *standard_iter << "\n";

        array<int, 5>::const_iterator standard_const_iter = arr.cbegin();
        standard_const_iter += 2;
        cout << *standard_const_iter << "\n";

        standard_const_iter = standard_iter;
        cout << *standard_const_iter << "\n";

        verify_convertible<array<int, 5>::iterator, array<int, 5>::const_iterator>();
        verify_NOT_convertible<array<Derived, 5>::iterator, array<Base, 5>::iterator>();
    }

    {
        checked_array_iterator<int*> checked_iter{arr.data(), arr.size()};
        checked_iter += 1;
        cout << *checked_iter << "\n";

        checked_array_iterator<const int*> checked_const_iter{arr.data(), arr.size()};
        checked_const_iter += 2;
        cout << *checked_const_iter << "\n";

#ifndef AVOID_ERRORS
        checked_const_iter = checked_iter;
        cout << *checked_const_iter << "\n";

        verify_convertible<checked_array_iterator<int*>, checked_array_iterator<const int*>>();
        verify_NOT_convertible<checked_array_iterator<Derived*>, checked_array_iterator<Base*>>();
#endif // AVOID_ERRORS
    }

    {
        unchecked_array_iterator<int*> unchecked_iter{arr.data()};
        unchecked_iter += 3;
        cout << *unchecked_iter << "\n";

        unchecked_array_iterator<const int*> unchecked_const_iter{arr.data()};
        unchecked_const_iter += 4;
        cout << *unchecked_const_iter << "\n";

#ifndef AVOID_ERRORS
        unchecked_const_iter = unchecked_iter;
        cout << *unchecked_const_iter << "\n";

        verify_convertible<unchecked_array_iterator<int*>, unchecked_array_iterator<const int*>>();
        verify_NOT_convertible<unchecked_array_iterator<Derived*>, unchecked_array_iterator<Base*>>();
#endif // AVOID_ERRORS
    }
}

C:\Temp>cl /EHsc /nologo /W4 /DAVOID_ERRORS meow.cpp && meow
meow.cpp
20
30
20
20
30
40
50

C:\Temp>cl /EHsc /nologo /W4 meow.cpp && meow
meow.cpp
meow.cpp(57): error C2679: binary '=': no operator found which takes a right-hand operand of type 'stdext::checked_array_iterator<int *>' (or there is no acceptable conversion)
C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\VC\Tools\MSVC\14.27.29009\include\iterator(710): note: could be 'stdext::checked_array_iterator<const int *> &stdext::checked_array_iterator<const int *>::operator =(stdext::checked_array_iterator<const int *> &&)'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\VC\Tools\MSVC\14.27.29009\include\iterator(710): note: or       'stdext::checked_array_iterator<const int *> &stdext::checked_array_iterator<const int *>::operator =(const stdext::checked_array_iterator<const int *> &)'
meow.cpp(57): note: while trying to match the argument list '(stdext::checked_array_iterator<const int *>, stdext::checked_array_iterator<int *>)'
meow.cpp(75): error C2679: binary '=': no operator found which takes a right-hand operand of type 'stdext::unchecked_array_iterator<int *>' (or there is no acceptable conversion)
C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\VC\Tools\MSVC\14.27.29009\include\iterator(850): note: could be 'stdext::unchecked_array_iterator<const int *> &stdext::unchecked_array_iterator<const int *>::operator =(stdext::unchecked_array_iterator<const int *> &&)'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\VC\Tools\MSVC\14.27.29009\include\iterator(850): note: or       'stdext::unchecked_array_iterator<const int *> &stdext::unchecked_array_iterator<const int *>::operator =(const stdext::unchecked_array_iterator<const int *> &)'
meow.cpp(75): note: while trying to match the argument list '(stdext::unchecked_array_iterator<const int *>, stdext::unchecked_array_iterator<int *>)'

Expected behavior
Code should compile.

STL version
Visual Studio Community 2019 Preview
16.7.0 Preview 3.1

Additional context
This item is also tracked on Developer Community as DevCom-241515 and by Microsoft-internal VSO-146139 / AB#146139.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementSomething can be improvedfixedSomething works now, yay!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions