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

Defer Invokable test in ranges::action #634

Merged
merged 5 commits into from
Apr 12, 2017
Merged

Conversation

ericniebler
Copy link
Owner

Also:

  • fix up many action concept tests
  • add tests for action::stable_sort and action::view

fixes #632

@tonyelewis
Copy link
Contributor

Thanks very much for looking into this so quickly.

I'm finding that this PR fixes my Clang but breaks my GCC 6.2.0 (coloured diagnostics in attached file) :

In file included from range-v3/include/range/v3/range_fwd.hpp:20:0,
                 from range-v3/include/range/v3/begin_end.hpp:22,
                 from range-v3/include/range/v3/core.hpp:17,
                 from range-v3/include/range/v3/all.hpp:17,
                 from range-v3.issue-632.cpp:1:
range-v3/include/meta/meta.hpp: In instantiation of ‘struct meta::v1::detail::_and_<meta::v1::defer<meta::v1::invoke, meta::v1::compose<meta::v1::bind_back<meta::v1::quote<ranges::v3::Sortable>, const volatile ranges::v3::less&, const volatile main()::<lambda(const int&)>&>, meta::v1::quote<ranges::v3::concepts::Range::iterator_t> >, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false> > >’:
range-v3/include/meta/meta.hpp:1137:20:   required from ‘struct meta::v1::detail::_and_<ranges::v3::concepts::models<ranges::v3::concepts::ForwardRange, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false> >, meta::v1::defer<meta::v1::invoke, meta::v1::compose<meta::v1::bind_back<meta::v1::quote<ranges::v3::Sortable>, const volatile ranges::v3::less&, const volatile main()::<lambda(const int&)>&>, meta::v1::quote<ranges::v3::concepts::Range::iterator_t> >, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false> > >’
range-v3/include/range/v3/action/sort.hpp:65:21:   required by substitution of ‘template<class Rng, class C, class P, int _concept_requires_65, typename std::enable_if<((_concept_requires_65 == 43) || (! typename meta::v1::detail::_and_<ranges::v3::concepts::models<ranges::v3::concepts::ForwardRange, T>, meta::v1::defer<meta::v1::invoke, meta::v1::compose<meta::v1::bind_back<meta::v1::quote<ranges::v3::Sortable>, C, P>, meta::v1::quote<ranges::v3::concepts::Range::iterator_t> >, Rng> >::type())), int>::type <anonymous> > void ranges::v3::action::stable_sort_fn::operator()(Rng&&, C&&, P&&) const [with Rng = ranges::v3::reference_wrapper<std::vector<int>, false>; C = const volatile ranges::v3::less&; P = const volatile main()::<lambda(const int&)>&; int _concept_requires_65 = 42; typename std::enable_if<((_concept_requires_65 == 43) || (! typename meta::v1::detail::_and_<ranges::v3::concepts::models<ranges::v3::concepts::ForwardRange, T>, meta::v1::defer<meta::v1::invoke, meta::v1::compose<meta::v1::bind_back<meta::v1::quote<ranges::v3::Sortable>, C, P>, meta::v1::quote<ranges::v3::concepts::Range::iterator_t> >, Rng> >::type())), int>::type <anonymous> = <missing>]’
/usr/include/c++/6/functional:1036:64:   required by substitution of ‘template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const volatile [with _Args = {ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false>}; _Result = <missing>]’
range-v3/include/range/v3/utility/invoke.hpp:125:13:   required by substitution of ‘template<class F, class ... Args, typename meta::v1::detail::_if_<meta::v1::list<std::integral_constant<bool, (! std::is_member_pointer<typename std::remove_cv<typename std::remove_reference<_From>::type>::type>::value)>, int>, std::integral_constant<bool, true> >::type <anonymous> > constexpr decltype (static_cast<F&&>(fn)(static_cast<Args&>(ranges::v3::invoke_fn::operator()::args) ...)) ranges::v3::invoke_fn::operator()(F&&, Args&& ...) const [with F = std::_Bind<ranges::v3::action::stable_sort_fn(std::_Placeholder<1>, ranges::v3::less, main()::<lambda(const int&)>)>&; Args = {ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false>}; typename meta::v1::detail::_if_<meta::v1::list<std::integral_constant<bool, (! std::is_member_pointer<typename std::remove_cv<typename std::remove_reference<_From>::type>::type>::value)>, int>, std::integral_constant<bool, true> >::type <anonymous> = 0]’
range-v3/include/range/v3/utility/invoke.hpp:171:28:   required by substitution of ‘template<class T> T ranges::v3::detail::gcc_bugs_bugs_bugs(T) [with T = <missing>]’
range-v3/include/range/v3/utility/concepts.hpp:111:55:   [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
range-v3/include/range/v3/utility/invoke.hpp:125:13:   required by substitution of ‘template<class F, class ... Args, typename meta::v1::detail::_if_<meta::v1::list<std::integral_constant<bool, (! std::is_member_pointer<typename std::remove_cv<typename std::remove_reference<_From>::type>::type>::value)>, int>, std::integral_constant<bool, true> >::type <anonymous> > constexpr decltype (static_cast<F&&>(fn)(static_cast<Args&>(ranges::v3::invoke_fn::operator()::args) ...)) ranges::v3::invoke_fn::operator()(F&&, Args&& ...) const [with F = ranges::v3::bitwise_or; Args = {ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false>, ranges::v3::action::action<std::_Bind<ranges::v3::action::stable_sort_fn(std::_Placeholder<1>, ranges::v3::less, main()::<lambda(const int&)>)> >&}; typename meta::v1::detail::_if_<meta::v1::list<std::integral_constant<bool, (! std::is_member_pointer<typename std::remove_cv<typename std::remove_reference<_From>::type>::type>::value)>, int>, std::integral_constant<bool, true> >::type <anonymous> = 0]’
range-v3/include/range/v3/utility/invoke.hpp:171:28:   required by substitution of ‘template<class T> T ranges::v3::detail::gcc_bugs_bugs_bugs(T) [with T = <missing>]’
range-v3/include/range/v3/utility/concepts.hpp:111:55:   required by substitution of ‘template<class ... Ts, class Concept, class> meta::v1::apply<meta::v1::quote<meta::v1::lazy::strict_and>, typename meta::v1::detail::transform_<meta::v1::list<typename ranges::v3::detail::base_concepts_of<Concept, void>::type, meta::v1::bind_back<meta::v1::quote<ranges::v3::concepts::models>, Ts ...> >, void>::type> ranges::v3::detail::models_(Concept*) [with Ts = {ranges::v3::bitwise_or, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false>, ranges::v3::action::action<std::_Bind<ranges::v3::action::stable_sort_fn(std::_Placeholder<1>, ranges::v3::less, main()::<lambda(const int&)>)> >&}; Concept = ranges::v3::concepts::Invocable; <template-parameter-1-3> = <missing>]’
range-v3/include/range/v3/utility/concepts.hpp:187:69:   required from ‘struct ranges::v3::concepts::models<ranges::v3::concepts::Invocable, ranges::v3::bitwise_or, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false>, ranges::v3::action::action<std::_Bind<ranges::v3::action::stable_sort_fn(std::_Placeholder<1>, ranges::v3::less, main()::<lambda(const int&)>)> >&>’
range-v3/include/range/v3/action/action.hpp:132:17:   required by substitution of ‘template<class Rng, class Action, int _concept_requires_135, typename std::enable_if<((_concept_requires_135 == 43) || (((ranges::v3::is_pipeable<Pipe>() && ranges::v3::concepts::models<ranges::v3::concepts::Range, T&>()) && ranges::v3::concepts::models<ranges::v3::concepts::Invocable, ranges::v3::bitwise_or, decltype (ranges::v3::{anonymous}::ref(declval<Rng&>())), Action&>()) && typename ranges::v3::concepts::Same::same<decltype (ranges::v3::{anonymous}::ref(declval<Rng&>())), typename ranges::v3::result_of<ranges::v3::bitwise_or(decltype (ranges::v3::{anonymous}::ref(declval<Rng&>()))&&, Action&), void>::type>::type())), int>::type <anonymous> > Rng& ranges::v3::action::operator|=(Rng&, Action&&) [with Rng = std::vector<int>; Action = ranges::v3::action::action<std::_Bind<ranges::v3::action::stable_sort_fn(std::_Placeholder<1>, ranges::v3::less, main()::<lambda(const int&)>)> >; int _concept_requires_135 = 42; typename std::enable_if<((_concept_requires_135 == 43) || (((ranges::v3::is_pipeable<Pipe>() && ranges::v3::concepts::models<ranges::v3::concepts::Range, T&>()) && ranges::v3::concepts::models<ranges::v3::concepts::Invocable, ranges::v3::bitwise_or, decltype (ranges::v3::{anonymous}::ref(declval<Rng&>())), Action&>()) && typename ranges::v3::concepts::Same::same<decltype (ranges::v3::{anonymous}::ref(declval<Rng&>())), typename ranges::v3::result_of<ranges::v3::bitwise_or(decltype (ranges::v3::{anonymous}::ref(declval<Rng&>()))&&, Action&), void>::type>::type())), int>::type <anonymous> = <missing>]’
range-v3.issue-632.cpp:13:2:   required from here
range-v3/include/meta/meta.hpp:1138:24: error: no type named ‘type’ in ‘struct meta::v1::defer<meta::v1::invoke, meta::v1::compose<meta::v1::bind_back<meta::v1::quote<ranges::v3::Sortable>, const volatile ranges::v3::less&, const volatile main()::<lambda(const int&)>&>, meta::v1::quote<ranges::v3::concepts::Range::iterator_t> >, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false> >’
                 : if_c<!Bool_::type::value, std::false_type, _and_<Bools...>>
                        ^~~~~~
range-v3/include/meta/meta.hpp: In instantiation of ‘struct meta::v1::detail::_and_<meta::v1::defer<meta::v1::invoke, meta::v1::compose<meta::v1::bind_back<meta::v1::quote<ranges::v3::Sortable>, volatile ranges::v3::less&, volatile main()::<lambda(const int&)>&>, meta::v1::quote<ranges::v3::concepts::Range::iterator_t> >, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false> > >’:
range-v3/include/meta/meta.hpp:1137:20:   required from ‘struct meta::v1::detail::_and_<ranges::v3::concepts::models<ranges::v3::concepts::ForwardRange, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false> >, meta::v1::defer<meta::v1::invoke, meta::v1::compose<meta::v1::bind_back<meta::v1::quote<ranges::v3::Sortable>, volatile ranges::v3::less&, volatile main()::<lambda(const int&)>&>, meta::v1::quote<ranges::v3::concepts::Range::iterator_t> >, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false> > >’
range-v3/include/range/v3/action/sort.hpp:65:21:   required by substitution of ‘template<class Rng, class C, class P, int _concept_requires_65, typename std::enable_if<((_concept_requires_65 == 43) || (! typename meta::v1::detail::_and_<ranges::v3::concepts::models<ranges::v3::concepts::ForwardRange, T>, meta::v1::defer<meta::v1::invoke, meta::v1::compose<meta::v1::bind_back<meta::v1::quote<ranges::v3::Sortable>, C, P>, meta::v1::quote<ranges::v3::concepts::Range::iterator_t> >, Rng> >::type())), int>::type <anonymous> > void ranges::v3::action::stable_sort_fn::operator()(Rng&&, C&&, P&&) const [with Rng = ranges::v3::reference_wrapper<std::vector<int>, false>; C = volatile ranges::v3::less&; P = volatile main()::<lambda(const int&)>&; int _concept_requires_65 = 42; typename std::enable_if<((_concept_requires_65 == 43) || (! typename meta::v1::detail::_and_<ranges::v3::concepts::models<ranges::v3::concepts::ForwardRange, T>, meta::v1::defer<meta::v1::invoke, meta::v1::compose<meta::v1::bind_back<meta::v1::quote<ranges::v3::Sortable>, C, P>, meta::v1::quote<ranges::v3::concepts::Range::iterator_t> >, Rng> >::type())), int>::type <anonymous> = <missing>]’
/usr/include/c++/6/functional:1022:70:   required by substitution of ‘template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) volatile [with _Args = {ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false>}; _Result = <missing>]’
range-v3/include/range/v3/utility/invoke.hpp:125:13:   required by substitution of ‘template<class F, class ... Args, typename meta::v1::detail::_if_<meta::v1::list<std::integral_constant<bool, (! std::is_member_pointer<typename std::remove_cv<typename std::remove_reference<_From>::type>::type>::value)>, int>, std::integral_constant<bool, true> >::type <anonymous> > constexpr decltype (static_cast<F&&>(fn)(static_cast<Args&>(ranges::v3::invoke_fn::operator()::args) ...)) ranges::v3::invoke_fn::operator()(F&&, Args&& ...) const [with F = std::_Bind<ranges::v3::action::stable_sort_fn(std::_Placeholder<1>, ranges::v3::less, main()::<lambda(const int&)>)>&; Args = {ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false>}; typename meta::v1::detail::_if_<meta::v1::list<std::integral_constant<bool, (! std::is_member_pointer<typename std::remove_cv<typename std::remove_reference<_From>::type>::type>::value)>, int>, std::integral_constant<bool, true> >::type <anonymous> = 0]’
range-v3/include/range/v3/utility/invoke.hpp:171:28:   required by substitution of ‘template<class T> T ranges::v3::detail::gcc_bugs_bugs_bugs(T) [with T = <missing>]’
range-v3/include/range/v3/utility/concepts.hpp:111:55:   [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
range-v3/include/range/v3/utility/invoke.hpp:125:13:   required by substitution of ‘template<class F, class ... Args, typename meta::v1::detail::_if_<meta::v1::list<std::integral_constant<bool, (! std::is_member_pointer<typename std::remove_cv<typename std::remove_reference<_From>::type>::type>::value)>, int>, std::integral_constant<bool, true> >::type <anonymous> > constexpr decltype (static_cast<F&&>(fn)(static_cast<Args&>(ranges::v3::invoke_fn::operator()::args) ...)) ranges::v3::invoke_fn::operator()(F&&, Args&& ...) const [with F = ranges::v3::bitwise_or; Args = {ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false>, ranges::v3::action::action<std::_Bind<ranges::v3::action::stable_sort_fn(std::_Placeholder<1>, ranges::v3::less, main()::<lambda(const int&)>)> >&}; typename meta::v1::detail::_if_<meta::v1::list<std::integral_constant<bool, (! std::is_member_pointer<typename std::remove_cv<typename std::remove_reference<_From>::type>::type>::value)>, int>, std::integral_constant<bool, true> >::type <anonymous> = 0]’
range-v3/include/range/v3/utility/invoke.hpp:171:28:   required by substitution of ‘template<class T> T ranges::v3::detail::gcc_bugs_bugs_bugs(T) [with T = <missing>]’
range-v3/include/range/v3/utility/concepts.hpp:111:55:   required by substitution of ‘template<class ... Ts, class Concept, class> meta::v1::apply<meta::v1::quote<meta::v1::lazy::strict_and>, typename meta::v1::detail::transform_<meta::v1::list<typename ranges::v3::detail::base_concepts_of<Concept, void>::type, meta::v1::bind_back<meta::v1::quote<ranges::v3::concepts::models>, Ts ...> >, void>::type> ranges::v3::detail::models_(Concept*) [with Ts = {ranges::v3::bitwise_or, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false>, ranges::v3::action::action<std::_Bind<ranges::v3::action::stable_sort_fn(std::_Placeholder<1>, ranges::v3::less, main()::<lambda(const int&)>)> >&}; Concept = ranges::v3::concepts::Invocable; <template-parameter-1-3> = <missing>]’
range-v3/include/range/v3/utility/concepts.hpp:187:69:   required from ‘struct ranges::v3::concepts::models<ranges::v3::concepts::Invocable, ranges::v3::bitwise_or, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false>, ranges::v3::action::action<std::_Bind<ranges::v3::action::stable_sort_fn(std::_Placeholder<1>, ranges::v3::less, main()::<lambda(const int&)>)> >&>’
range-v3/include/range/v3/action/action.hpp:132:17:   required by substitution of ‘template<class Rng, class Action, int _concept_requires_135, typename std::enable_if<((_concept_requires_135 == 43) || (((ranges::v3::is_pipeable<Pipe>() && ranges::v3::concepts::models<ranges::v3::concepts::Range, T&>()) && ranges::v3::concepts::models<ranges::v3::concepts::Invocable, ranges::v3::bitwise_or, decltype (ranges::v3::{anonymous}::ref(declval<Rng&>())), Action&>()) && typename ranges::v3::concepts::Same::same<decltype (ranges::v3::{anonymous}::ref(declval<Rng&>())), typename ranges::v3::result_of<ranges::v3::bitwise_or(decltype (ranges::v3::{anonymous}::ref(declval<Rng&>()))&&, Action&), void>::type>::type())), int>::type <anonymous> > Rng& ranges::v3::action::operator|=(Rng&, Action&&) [with Rng = std::vector<int>; Action = ranges::v3::action::action<std::_Bind<ranges::v3::action::stable_sort_fn(std::_Placeholder<1>, ranges::v3::less, main()::<lambda(const int&)>)> >; int _concept_requires_135 = 42; typename std::enable_if<((_concept_requires_135 == 43) || (((ranges::v3::is_pipeable<Pipe>() && ranges::v3::concepts::models<ranges::v3::concepts::Range, T&>()) && ranges::v3::concepts::models<ranges::v3::concepts::Invocable, ranges::v3::bitwise_or, decltype (ranges::v3::{anonymous}::ref(declval<Rng&>())), Action&>()) && typename ranges::v3::concepts::Same::same<decltype (ranges::v3::{anonymous}::ref(declval<Rng&>())), typename ranges::v3::result_of<ranges::v3::bitwise_or(decltype (ranges::v3::{anonymous}::ref(declval<Rng&>()))&&, Action&), void>::type>::type())), int>::type <anonymous> = <missing>]’
range-v3.issue-632.cpp:13:2:   required from here
range-v3/include/meta/meta.hpp:1138:24: error: no type named ‘type’ in ‘struct meta::v1::defer<meta::v1::invoke, meta::v1::compose<meta::v1::bind_back<meta::v1::quote<ranges::v3::Sortable>, volatile ranges::v3::less&, volatile main()::<lambda(const int&)>&>, meta::v1::quote<ranges::v3::concepts::Range::iterator_t> >, ranges::v3::reference_wrapper<std::vector<int, std::allocator<int> >, false> >’

475a1e0.gcc_colour.txt

meta::compose<
meta::bind_back<meta::quote<Sortable>, C, P>,
meta::quote<iterator_t>>,
Rng>>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constraint is identical to that in action/sort.hpp. Should we factor it out into a SortableRange concept?

#include "../simple_test.hpp"
#include "../test_utils.hpp"

template<class> struct undef;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've left your type printer debugging tool in the code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With a more descriptive name - I always call it show_type and make it variadic - it would be a good idea to put an intentionally undefined template in e.g. test_utils. It would not suck to never have to type this line of code again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always call it dump, would be nice to have this in test_utils.

{
using namespace ranges;

std::vector<std::string> v {"hello"," ","world"};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#include <string>

@ericniebler
Copy link
Owner Author

I borrowed some ideas from @odinthenerd to make meta::and_ and meta::or_ SFINAE-friendly and compile faster. Let's see what Travis makes of this.

@ericniebler
Copy link
Owner Author

I'm really struggling getting this to compile on Clang 3.6 and GCC 4.8. If anybody thinks they can do it I would gladly accept help.

@tonyelewis
Copy link
Contributor

FWIW, I can confirm that the PR has now fixed #632 for me on Clang 3.8.1 and GCC 6.2.0.

I'd be happy to help but it's very doubtful that I'd make more progress than you.

@tonyelewis
Copy link
Contributor

FYI: at da45d36, my original #632 code is still working under both Clang 3.8.1 and GCC 6.2.0.

@ericniebler ericniebler force-pushed the fix-action-concepts branch from da45d36 to d372008 Compare April 11, 2017 23:51
@ericniebler
Copy link
Owner Author

Attn @CaseyCarter : I have rebased this branch. Be careful.

@tonyelewis
Copy link
Contributor

FYI: at the rebased tip d372008, my original #632 code is still working under both Clang 3.8.1 and GCC 6.2.0.

@CaseyCarter
Copy link
Collaborator

This has been a ridiculously complicated bug fix. We really should ban @tonyelewis ;)

@ericniebler
Copy link
Owner Author

Eagerly anticipating a time when I can drop gcc-4.x support.

@CaseyCarter
Copy link
Collaborator

I'm really struggling getting this to compile on Clang 3.6 and GCC 4.8

I really hope this "4.8" is a typo. 141 of 203 tests ICE on utility/concepts.hpp line 111 for me compiling with 4.8.

@ericniebler
Copy link
Owner Author

Yes, I meant gcc-4.9. I dropped gcc-4.8 with the 0.2.0 release, and there's no going back now.

@ericniebler ericniebler force-pushed the fix-action-concepts branch from 9862bdb to e963356 Compare April 12, 2017 23:55
@ericniebler ericniebler merged commit 3905c46 into master Apr 12, 2017
@ericniebler ericniebler deleted the fix-action-concepts branch April 12, 2017 23:56
@ericniebler
Copy link
Owner Author

FINALLY.

@tonyelewis
Copy link
Contributor

Apologies for being a trouble-causer. ;)

@tonyelewis
Copy link
Contributor

I like the implementation of std::is_function. It took me a few moments to decipher it because I'm not massively familiar with a few of the techniques 😕. Is the priority_tag approach novel?

@CaseyCarter
Copy link
Collaborator

Is the priority_tag approach novel?

I picked up the technique on Stackoverflow years ago; I've seen it attributed to Xeo. In addition to being more extensible, I think it expresses intent far more clearly than ad-hoc int vs. long vs. nullptr_t vs. ... overloading.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

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