ericniebler / range-v3

Range library for C++14/17/20, basis for C++20's std::ranges

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

action::stable_sort of vector broken on Clang 3.8.1 since ~last Xmas

tonyelewis opened this issue · comments

This code used to compile and run under Clang 3.8.1:

#include <range/v3/all.hpp>

#include <iostream>
#include <vector>

int main() {
	const std::vector<double> scores = { 3.0, 1.0, 2.0 };
	std::vector<int> indices = { 0, 1, 2 };

	indices |= ranges::action::stable_sort(
		ranges::less{},
		[&] (const int &x) { return scores[ x ]; }
	);

	std::cerr << ( indices | ranges::view::all ) << "\n";
}

...but since 6191722, it gives errors:

In file included from range-v3.stable-sort-prob.cpp:1:
In file included from range-v3/include/range/v3/all.hpp:19:
In file included from range-v3/include/range/v3/action.hpp:30:
range-v3/include/range/v3/action/stable_sort.hpp:73:21: error: static_assert failed "The object on which action::stable_sort operates must be a model of the ForwardRange concept."
                    CONCEPT_ASSERT_MSG(ForwardRange<Rng>(),
                    ^                  ~~~~~~~~~~~~~~~~~~~
range-v3/include/range/v3/utility/concepts.hpp:812:28: note: expanded from macro 'CONCEPT_ASSERT_MSG'
#define CONCEPT_ASSERT_MSG static_assert
                           ^
range-v3/include/range/v3/utility/invoke.hpp:124:17: note: in instantiation of function template specialization 'ranges::v3::action::stable_sort_fn::operator()<ranges::v3::less &, (lambda at range-v3.stable-sort-prob.cpp:12:3), ranges::v3::ident, 42, 0>' requested here
                detail::forward<F>(fn)(detail::forward<Args>(args)...)
                ^
In file included from range-v3.stable-sort-prob.cpp:1:
In file included from range-v3/include/range/v3/all.hpp:17:
In file included from range-v3/include/range/v3/core.hpp:18:
In file included from range-v3/include/range/v3/distance.hpp:22:
In file included from range-v3/include/range/v3/range_traits.hpp:24:
range-v3/include/range/v3/range_concepts.hpp:64:45: error: no matching function for call to object of type 'const ranges::v3::adl_begin_end_detail::begin_fn'
                using iterator_t = decltype(begin(std::declval<T&>()));
                                            ^~~~~
range-v3/include/range/v3/range_traits.hpp:35:9: note: in instantiation of template type alias 'iterator_t' requested here
        using range_iterator_t = concepts::Range::iterator_t<Rng>;
        ^
range-v3/include/range/v3/action/stable_sort.hpp:76:31: note: in instantiation of template type alias 'range_iterator_t' requested here
                    using I = range_iterator_t<Rng>;
                              ^
range-v3/include/range/v3/utility/invoke.hpp:124:17: note: in instantiation of function template specialization 'ranges::v3::action::stable_sort_fn::operator()<ranges::v3::less &, (lambda at range-v3.stable-sort-prob.cpp:12:3), ranges::v3::ident, 42, 0>' requested here
                detail::forward<F>(fn)(detail::forward<Args>(args)...)
                ^
range-v3/include/range/v3/begin_end.hpp:105:32: note: candidate template ignored: substitution failure [with Rng = ranges::v3::less &]: no matching function for call to 'impl'
                constexpr auto operator()(Rng && rng) const
                               ^
In file included from range-v3.stable-sort-prob.cpp:1:
In file included from range-v3/include/range/v3/all.hpp:19:
In file included from range-v3/include/range/v3/action.hpp:30:
range-v3/include/range/v3/action/stable_sort.hpp:77:21: error: static_assert failed "The projection function must accept objects of the iterator's value type, reference type, and common reference type."
                    CONCEPT_ASSERT_MSG(IndirectInvocable<P, I>(),
                    ^                  ~~~~~~~~~~~~~~~~~~~~~~~~~
range-v3/include/range/v3/utility/concepts.hpp:812:28: note: expanded from macro 'CONCEPT_ASSERT_MSG'
#define CONCEPT_ASSERT_MSG static_assert
                           ^
range-v3/include/range/v3/utility/invoke.hpp:124:17: note: in instantiation of function template specialization 'ranges::v3::action::stable_sort_fn::operator()<ranges::v3::less &, (lambda at range-v3.stable-sort-prob.cpp:12:3), ranges::v3::ident, 42, 0>' requested here
                detail::forward<F>(fn)(detail::forward<Args>(args)...)
                ^
In file included from range-v3.stable-sort-prob.cpp:1:
In file included from range-v3/include/range/v3/all.hpp:17:
In file included from range-v3/include/range/v3/core.hpp:17:
In file included from range-v3/include/range/v3/begin_end.hpp:21:
In file included from range-v3/include/range/v3/range_fwd.hpp:20:
range-v3/include/meta/meta.hpp:140:9: error: no type named 'type' in 'meta::v1::detail::_if_<meta::v1::list<std::__1::integral_constant<bool, false>, ranges::v3::detail::projected_<int, ranges::v3::ident> >, bool>'
        using _t = typename T::type;
        ^~~~~
range-v3/include/meta/meta.hpp:1110:9: note: in instantiation of template type alias '_t' requested here
        using if_c = _t<detail::_if_<list<bool_<If>, Args...>>>;
        ^
range-v3/include/range/v3/utility/iterator_concepts.hpp:568:9: note: in instantiation of template type alias 'if_c' requested here
        using projected = meta::if_c<IndirectInvocable<Proj, I>::value, detail::projected_<I, Proj>>;
        ^
range-v3/include/range/v3/action/stable_sort.hpp:80:60: note: in instantiation of template type alias 'projected' requested here
                    CONCEPT_ASSERT_MSG(IndirectRelation<C, projected<I, P>>(),
                                                           ^
range-v3/include/range/v3/utility/invoke.hpp:124:17: note: in instantiation of function template specialization 'ranges::v3::action::stable_sort_fn::operator()<ranges::v3::less &, (lambda at range-v3.stable-sort-prob.cpp:12:3), ranges::v3::ident, 42, 0>' requested here
                detail::forward<F>(fn)(detail::forward<Args>(args)...)
                ^
4 errors generated.

From what I can see on Wandbox, the problem disappears for Clang ≥ 4.0.

Sorry: I forgot to say that this works without problem under GCC.

Workaround:

-indices |= ranges::action::stable_sort(
+ranges::action::stable_sort(indices,

...which should suggest where the problem lies.

sort-of minimized repro:

#include <range/v3/action/stable_sort.hpp>

int main() {
    int ints[1] = {};
#ifndef WORKAROUND
    ints |= ranges::action::stable_sort(ranges::less{});
#else
    ranges::action::stable_sort(ints, ranges::less{});
#endif
}

Thanks so much for this quick response and pointer on how I can work around the issue. Apologies for not having minimised further myself.

PR #634 should fix this.

As I've commented on #634, I'm finding that it fixes my Clang but breaks my GCC.

This works for me. Thanks so much for all your work on this.