I am trying to write a wrapper around a container that is a bidirectional range and is able to store smart pointers. As a result, I want to write the wrapper and iterator for the same. The class does not work properly, and its mostly because I lack adequate knowledge. So currently, forEach loop works, but any_of does not compile. So help needed in pointing out problems, and maybe pointing towards some resources that might help.
#Help needed with custom iterator class for container wrapper
28 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
I wrote the main function just to test compilation. any_of does not compile, throwing error that it cannot find __begin for the container, that the container does not support:-
Here's the error from clang
that's not quite what the error excerpt complains about, but eh, close enough I guess?
like the closest mention of some __begin in that excerpt is const ranges::__access::_Begin at the end, so I assume you're referring to a different compiler/configuration when you say __begin
assuming that __begin and that other _Begin have somewhat similar roles in either standard library, you're likely looking at the wrong part of the error message
the error you have is that std::ranges::any_of doesn't work out, because there were no valid overloads found for the set of arguments you provided
the way that kind of error is structured, is that the compiler lists all the candidates it is aware of in the context of the call, and provide explanations for why the overload was discarded (when all are discarded, when the error is due to ambituity between multiple overloads it's phrased differently)
the section talking about _Begin explains why an overload you don't care about has failed, so you should focus on the other section
in your code, you wrote std::ranges::any_of(cont.begin(), cont.end(), [](auto t){ return true;}); so you specifically do not "care" about
overload 2 (in the error) operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
you care about overload 1 (in the error) operator()(_Iter __first, _Sent __last,
note that the rest of the signature is cutoff in the error, but the point is you passed in begin/end, not the range directly
so the next part is looking at why that overload 1 was not eligible/valid, which the compiler explains a little here
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/bits/ranges_algo.h:104:14: note: because 'utility::c_container<std::basic_string<char>, std::weak_ptr>::c_iterator<>' does not satisfy 'input_iterator'
104 | template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/bits/iterator_concepts.h:656:10: note: because 'utility::c_container<std::basic_string<char>, std::weak_ptr>::c_iterator<>' does not satisfy 'indirectly_readable'
656 | && indirectly_readable<_Iter>
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/bits/iterator_concepts.h:553:9: note: because 'remove_cvref_t<c_iterator<false, false>>' (aka 'utility::c_container<std::basic_string<char>, std::weak_ptr>::c_iterator<>') does not satisfy '__indirectly_readable_impl'
553 | = __detail::__indirectly_readable_impl<remove_cvref_t<_In>>;
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/bits/iterator_concepts.h:537:19: note: because 'same_as<iter_reference_t<const _In>, iter_reference_t<_In>>' would be invalid: constraints not satisfied for alias template 'iter_reference_t' [with _Tp = const utility::c_container<std::basic_string<char>, std::weak_ptr>::c_iterator<>]
537 | requires same_as<iter_reference_t<const _In>,
|
you get 4 notes
- your iterator type does not satisfy the concept input_iterator,
- because it does not satisfy the concept indirectly_readable,
- because it does not satisfy "implementation details" of indirectly_readable,
- because it does not satisfy
same_as<iter_reference_t<const _In>, iter_reference_t<_In>>where_Inis a placeholder for your iterator type
So, it is because the iterator to const T and T are different, hence the error?
template <bool is_const = false, bool is_reverse = false>
class c_iterator
{
public:
auto operator*() -> reference;
auto operator->() -> pointer;
};
these are wrong
no, it's because a const iterator to T and a non-const iterator to T do not provide the same type when dereferenced
because your iterator type cannot be dereferenced when constant
Yeah, I got that. I used the range overload earlier, and it was complaining about the sentinel value, and when I switched over to the begin/end overload, it complained about begin. I am a novice, so could not figure out what it meant to not satisfy the input_iterator trait.
because you required that it can only be used when non-const
Can you explain it a little bit more? Is it because the reference and pointer in the return type?
So, I need the two operators to work invariably over the template is_const?
your iterator type has auto operator*() -> reference;
that means you can only use *obj when obj is non-const
and you cannot do *std::as_const(obj)
or *const_obj
the problem I'm talking about is completely independent from is_const
if this isn't clear to you, "is const" governs the difference in behaviour between T* and T const*
the problem I'm talking about is between T* and T* const
you could change T to be U const and it would still be a problem (U const* vs U const* const)
This question is being automatically marked as stale.
If your question has been answered, type !solved.
If your question is not answered feel free to bump the post or re-ask.
Take a look at !howto ask for tips on improving your question.
!solved