Skip to content

Some custom iterators are incompatible with standard algorithms #946

@SamuelBeland

Description

@SamuelBeland

Containers that return raw pointers (like Array or SortedSet) work well with standard algorithms, but the ones that use custom iterators (like juce_CharPointer_UFT8 for strings or HashMap::Iterator) do not.

When compiling the following code with GCC-11...

#include <JuceHeader.h>

#include <algorithm>

static bool complex_test(juce::juce_wchar const c)
{
        /* do some complex test... */
        return c == 'o';
};

int main (int argc, char* argv[])
{
    juce::String const string{ "foo" };
    auto const valid{ std::all_of(string.begin(), string.end(), complex_test) };

    return valid ? 0 : 1;
}

...we get the following error :

In file included from /usr/include/c++/11/algorithm:62,
                 from ../../JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h:46,
                 from ../../JuceLibraryCode/modules/juce_core/juce_core.h:203,
                 from ../../JuceLibraryCode/JuceHeader.h:16,
                 from ../../Source/Main.cpp:1:
/usr/include/c++/11/bits/stl_algo.h: In instantiation of ‘_InputIterator std::__find_if_not(_InputIterator, _InputIterator, _Predicate) [with _InputIterator = juce::CharPointer_UTF8; _Predicate = __gnu_cxx::__ops::_Iter_pred<bool (*)(wchar_t)>]’:
/usr/include/c++/11/bits/stl_algo.h:513:32:   required from ‘_IIter std::find_if_not(_IIter, _IIter, _Predicate) [with _IIter = juce::CharPointer_UTF8; _Predicate = bool (*)(wchar_t)]’
/usr/include/c++/11/bits/stl_algo.h:453:40:   required from ‘bool std::all_of(_IIter, _IIter, _Predicate) [with _IIter = juce::CharPointer_UTF8; _Predicate = bool (*)(wchar_t)]’
../../Source/Main.cpp:14:34:   required from here
/usr/include/c++/11/bits/stl_algo.h:108:53: error: no matching function for call to ‘__iterator_category(juce::CharPointer_UTF8&)’
  108 |                             std::__iterator_category(__first));
      |                             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
In file included from /usr/include/c++/11/bits/stl_algobase.h:65,
                 from /usr/include/c++/11/algorithm:61,
                 from ../../JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h:46,
                 from ../../JuceLibraryCode/modules/juce_core/juce_core.h:203,
                 from ../../JuceLibraryCode/JuceHeader.h:16,
                 from ../../Source/Main.cpp:1:
/usr/include/c++/11/bits/stl_iterator_base_types.h:238:5: note: candidate: ‘template<class _Iter> constexpr typename std::iterator_traits< <template-parameter-1-1> >::iterator_category std::__iterator_category(const _Iter&)’
  238 |     __iterator_category(const _Iter&)
      |     ^~~~~~~~~~~~~~~~~~~
/usr/include/c++/11/bits/stl_iterator_base_types.h:238:5: note:   template argument deduction/substitution failed:
/usr/include/c++/11/bits/stl_iterator_base_types.h: In substitution of ‘template<class _Iter> constexpr typename std::iterator_traits< <template-parameter-1-1> >::iterator_category std::__iterator_category(const _Iter&) [with _Iter = juce::CharPointer_UTF8]’:
/usr/include/c++/11/bits/stl_algo.h:108:32:   required from ‘_InputIterator std::__find_if_not(_InputIterator, _InputIterator, _Predicate) [with _InputIterator = juce::CharPointer_UTF8; _Predicate = __gnu_cxx::__ops::_Iter_pred<bool (*)(wchar_t)>]’
/usr/include/c++/11/bits/stl_algo.h:513:32:   required from ‘_IIter std::find_if_not(_IIter, _IIter, _Predicate) [with _IIter = juce::CharPointer_UTF8; _Predicate = bool (*)(wchar_t)]’
/usr/include/c++/11/bits/stl_algo.h:453:40:   required from ‘bool std::all_of(_IIter, _IIter, _Predicate) [with _IIter = juce::CharPointer_UTF8; _Predicate = bool (*)(wchar_t)]’
../../Source/Main.cpp:14:34:   required from here
/usr/include/c++/11/bits/stl_iterator_base_types.h:238:5: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<juce::CharPointer_UTF8>’

Compilation also fails with Clang-10. MSVC compiles without problem.

If we define the standard iterator traits in juce_CharPointerUTF8, it seems to solve the issue.

class CharPointer_UTF8  final
{
public:
    using value_type = juce::juce_wchar;
    using pointer = value_type*;
    using reference = value_type&;
    using iterator_category = std::bidirectional_iterator_tag;
    
    // not sure if this last one makes sense, since
    // `int operator-(CharPointer_UTF8 lhs, CharPointer_UTF8 rhs);`
    // is not defined. Maybe it should?
    using difference_type = int; 

    // ...
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions