Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__bit_iterator is missing operator-> #111032

Open
cjdb opened this issue Oct 3, 2024 · 3 comments
Open

__bit_iterator is missing operator-> #111032

cjdb opened this issue Oct 3, 2024 · 3 comments
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Comments

@cjdb
Copy link
Contributor

cjdb commented Oct 3, 2024

Cpp17InputIterator requires a->m to be a valid production, which __bit_iterator lacks. Although bool doesn't have any members to access, it->~value_type() should still be valid due to pseudo-destructors.

@cjdb cjdb added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Oct 3, 2024
@Halalaluyafail3
Copy link

Is this a bug? std::vector<bool>::iterator already has some internal contradictions:

  1. std::vector<bool>::iterator pretends to be a random access iterator with how it defines iterator_category to be random_access_iterator_tag even though it can't satisfy the Cpp17ForwardIterator requirements because of how it defines reference.
  2. The container requirements [container.reqmts] requires std::vector<bool>::iterator to satisfy the Cpp17ForwardIterator requirements which is not possible, along with other things that std::vector<bool> doesn't satisfy.
  3. Before C++20 std::reverse_iterator required the iterator provided to satisfy the Cpp17BidirectionalIterator requirements which std::vector<bool>::iterator doesn't, and std::vector<bool>::reverse_iterator would immediately create std::reverse_iterator<std::vector<bool>::iterator>.

From what I understand this iterator type can't really meet the requirements it's supposed to, so perhaps not supporting the arrow operator as well is alright. libstdc++ and MSVC's standard library also don't provide arrow operator support for std::vector<bool>::iterator.

Lets suppose std::vector<bool>::iterator were to support the arrow operator anyways, following the requirements of Cpp17InputIterator. The requirements specify that an expression a->m is supposed to be equivalent to (*a).m. [iterator.cpp17] says that a denotes a value of type X or const X, and that m denotes an identifier. Given this, your example it->~value_type() should be invalid because ~value_type is not an identifier and because (*it).~value_type() wouldn't be valid either. The only valid uses of the arrow operator would be to access something from std::vector<bool>::reference with a single identifier. That is, calling the destructor, conversion operator to bool, or an assignment operator is not required to be supported. Only calling the member function flip like a->flip() is required to be supported. std::vector<bool>::const_iterator therefore doesn't need to support the arrow operator because flip is not a const member function.

struct fixed_iterator:std::vector<bool>::iterator{
    struct pointer{
        std::vector<bool>::reference ref;
        pointer*operator->(){
            return this;
        }
        void flip(){
            ref.flip();
        }
    };
    pointer operator->()const{
        return pointer{**this};
    }
};

This code seems to work to support this use case https://godbolt.org/z/7TvceKGWM, while not supporting invalid uses like calling the destructor of reference or value_type. So I think supporting the arrow operator is possible, though it shouldn't make it->~value_type() valid.

@frederick-vs-ja
Copy link
Contributor

  1. std::vector<bool>::iterator pretends to be a random access iterator with how it defines iterator_category to be random_access_iterator_tag even though it can't satisfy the Cpp17ForwardIterator requirements because of how it defines reference.

In the view of C++20 iterators, I think vector<bool>::iterator's iterator_category should be input_iterator_tag while its iterator_concept should be random_access_iterator_tag. The current implementation strategy (also used by MSVC STL & libstdc++) is not strictly conforming. Some concerns have been tracked in LWG1422.

If we make vector<bool>::iterator::iterator_category's iterator_category be input_iterator_tag, we may need more works to make non-ranges algorithms perform random position for them, and the standard wording should be fixed to ensure that operator<=> and many non-ranges algorithms that expect stricter-than-input iterators work for vector<bool>::iterator.

Given this, your example it->~value_type() should be invalid because ~value_type is not an identifier and because (*it).~value_type() wouldn't be valid either. The only valid uses of the arrow operator would be to access something from std::vector<bool>::reference with a single identifier.

Agreed. I don't think the original issue is a bug either.

Only calling the member function flip like a->flip() is required to be supported. std::vector<bool>::const_iterator therefore doesn't need to support the arrow operator because flip is not a const member function.

I think this should be right. But the standard wording is somehow underspecified on the value_type and reference of proxy iterators in [containers], for which I submitted LWG3966. It should be ensured that they're consistent with vector<bool> and flat_(multi_)map's members.

At this moment I agree on supporting it->flip() too.

@Halalaluyafail3
Copy link

  1. std::vector<bool>::iterator pretends to be a random access iterator with how it defines iterator_category to be random_access_iterator_tag even though it can't satisfy the Cpp17ForwardIterator requirements because of how it defines reference.

In the view of C++20 iterators, I think vector<bool>::iterator's iterator_category should be input_iterator_tag while its iterator_concept should be random_access_iterator_tag. The current implementation strategy (also used by MSVC STL & libstdc++) is not strictly conforming. Some concerns have been tracked in LWG1422.

That sounds like a good idea, by the way a lot of the range adapators in C++20 don't support the arrow operator and define iterator_category anyway. For example:

int x[]{1,2,3};
auto v=std::views::zip(x);
auto i=std::ranges::begin(v);

The expression (*i).swap(*i) is valid but not i->swap(*i), yet decltype(i)::iterator_category is std::input_iterator_tag. It seems like only std::views::filter and std::views::join attempt to support the arrow operator. std::move_iterator cannot possibly meet the requirements on the arrow operator because of how operator-> overloading works. So there is some precedent for not supporting the arrow operator even for iterators that are supposed to meet the pre-C++20 iterator requirements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

No branches or pull requests

3 participants