Open regehr opened 8 years ago
Another example (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72457):
namespace std {
typedef int size_t;
template <typename _Tp, _Tp __v> struct integral_constant {
static constexpr _Tp value = __v;
typedef integral_constant type;
constexpr operator int() { return 1; }
};
typedef integral_constant<int, 0> false_type;
template <typename...> struct __or_;
template <typename _B1, typename _B2> struct __or_<_B1, _B2> : _B2 {};
template <typename...> struct __and_;
template <typename _B1, typename _B2> struct __and_<_B1, _B2> : _B1 {};
template <typename _Pp> struct __not_ : integral_constant<int, !_Pp::value> {};
struct __is_void_helper : false_type {};
template <typename> struct is_void : __is_void_helper {};
template <typename _Tp> _Tp declval();
struct __is_default_constructible_atom : __and_<__not_<is_void<int>>, int> {};
template <typename>
struct __is_default_constructible_safe : __is_default_constructible_atom {};
template <typename>
struct is_default_constructible : __is_default_constructible_safe<int> {};
template <typename, typename> struct is_same : integral_constant<int, 0> {};
template <typename _Tp> struct decay { typedef _Tp type; };
template <int, typename> struct enable_if;
template <typename _Tp> struct enable_if<1, _Tp> { typedef _Tp type; };
template <typename _Tp> _Tp forward;
template <typename...> struct tuple;
template <typename> struct tuple_size;
template <typename> struct tuple_element;
template <typename _Tp, _Tp...> struct integer_sequence;
template <typename _Head, typename... _Tail>
struct tuple_element<tuple<_Head, _Tail...>> {
typedef _Head type;
};
template <typename... _Elements>
struct tuple_size<tuple<_Elements...>>
: integral_constant<int, sizeof...(_Elements)> {};
namespace placeholders {
int _1;
}
template <int, typename _Tuple>
using _Safe_tuple_element_t =
typename enable_if<tuple_size<_Tuple>::value,
tuple_element<_Tuple>>::type::type;
template <typename> struct _Mu {
template <typename _Tuple>
_Safe_tuple_element_t<0, _Tuple> operator()(int, _Tuple &);
};
template <typename> struct _Bind;
template <typename _Functor, typename... _Bound_args>
struct _Bind<_Functor(_Bound_args...)> {
template <typename... _Args,
typename _Result = decltype(_Functor()(
_Mu<_Bound_args>()(0, declval<tuple<_Args...> &>())...))>
_Result operator()(_Args...);
};
template <typename _Tp, typename _Tp2 = _Tp>
using __is_socketlike = __or_<_Tp2, integral_constant<int, 0>>;
template <int, typename _Func, typename... _BoundArgs> struct _Bind_helper {
typedef _Bind<_Func(_BoundArgs...)> type;
};
template <typename _Func, typename... _BoundArgs>
typename _Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type
bind(_Func, _BoundArgs...);
namespace {
template <typename...> struct list;
template <template <typename...> class, typename...> struct defer;
template <typename T> T *_nullptr_v();
template <typename T> using _t = typename T::type;
template <int> using size_t = integral_constant<int, 0>;
template <int> using bool_ = integral_constant<int, 0>;
namespace detail {
enum indices_strategy_ { recurse };
constexpr indices_strategy_ strategy_(std::size_t, std::size_t) {
return recurse;
}
template <std::size_t, typename State, indices_strategy_> struct make_indices_ {
using type = State;
};
}
template <long... Is> using index_sequence = integer_sequence<int, Is...>;
template <std::size_t>
using make_index_sequence =
_t<detail::make_indices_<0, index_sequence<>, detail::strategy_(0, 0)>>;
template <typename F, typename... Args>
using invoke = typename F::template invoke<Args...>;
namespace lazy {
template <typename F, typename... Args>
using invoke = defer<invoke, F, Args...>;
}
template <typename T> struct id { using type = T; };
namespace detail {
template <template <typename...> typename, typename> struct defer_;
template <template <typename...> class C, typename... Ts>
struct defer_<C, list<Ts...>> {
using type = C<Ts...>;
};
}
template <template <typename...> class C, typename... Ts>
struct defer : detail::defer_<C, list<Ts...>> {};
template <template <typename...> class C> struct quote {
template <typename... Ts> using invoke = _t<detail::defer_<C, list<Ts...>>>;
};
template <template <typename> class> using quote_trait = int;
template <typename F, typename... Ts> struct bind_front {
template <typename... Us> using invoke = invoke<F, Ts..., Us...>;
};
template <typename F, typename... Us> struct bind_back {
template <typename... Ts> using invoke = invoke<F, Ts..., Us...>;
};
namespace extension {
template <typename, typename> struct apply;
template <typename F, typename Ret, typename... Args>
struct apply<F, Ret(Args...)> : lazy::invoke<F, Args...> {};
}
template <typename C, typename List>
using apply = _t<extension::apply<C, List>>;
template <typename, typename Q = quote<list>> using curry = Q;
template <typename F> using uncurry = bind_front<quote<apply>, F>;
namespace detail {
template <typename> struct _if_;
template <typename If, typename Then> struct _if_<list<If, Then>> {
using type = Then;
};
}
template <typename... Args> using if_ = _t<detail::_if_<list<Args...>>>;
template <int If, typename... Args>
using if_c = _t<detail::_if_<list<bool_<If>, Args...>>>;
namespace lazy {
template <typename... Args> using if_ = defer<if_, Args...>;
}
template <bool... Bools>
using and_c = is_same<int, integer_sequence<int, Bools...>>;
template <typename... Bools> using strict_and = and_c<Bools::value...>;
namespace detail {
struct repeat_n_c_ {
using type = list<>;
};
}
template <int, typename> using repeat_n_c = _t<detail::repeat_n_c_>;
template <typename N, typename T> using repeat_n = repeat_n_c<N::value, T>;
namespace detail {
template <typename> struct at_impl_ {
template <typename T> static T eval(T *);
};
template <typename, typename> struct at_;
template <typename... Ts, typename N>
struct at_<list<Ts...>, N>
: decltype(at_impl_<repeat_n<N, void>>::eval(static_cast<id<Ts> *>(0)...)) {
};
}
template <typename List, typename N> using at = _t<detail::at_<List, N>>;
template <typename List, int> using at_c = at<List, size_t<0>>;
namespace detail {
template <typename> struct drop_impl_ {
template <typename... Ts> static id<list<Ts...>> eval(Ts...);
};
template <typename, typename> struct drop_;
template <typename... Ts, typename N>
struct drop_<list<Ts...>, N>
: decltype(drop_impl_<repeat_n<N, void>>::eval(_nullptr_v<Ts>...)) {};
}
template <typename List, int> using drop_c = _t<detail::drop_<List, size_t<0>>>;
namespace detail {
template <typename> struct back_;
template <typename Head, typename... List> struct back_<list<Head, List...>> {
using type = at_c<list<Head>, sizeof...(List)>;
};
}
template <typename List> using back = _t<detail::back_<List>>;
namespace detail {
template <typename, typename> struct find_if_;
template <typename... List, typename Fun> struct find_if_<list<List...>, Fun> {
static constexpr int s_v{invoke<Fun, List>::value...};
using type = drop_c<list<List...>, s_v>;
};
}
template <typename List, typename Fun>
using find_if = _t<detail::find_if_<List, Fun>>;
namespace detail {
template <typename Sequence>
struct as_list_ : lazy::invoke<uncurry<curry<quote_trait<id>>>, Sequence> {};
}
template <typename Sequence> using as_list = _t<detail::as_list_<Sequence>>;
}
namespace v3 {
namespace adl_begin_end_detail {
struct begin_fn;
}
using adl_begin_end_detail::begin_fn;
namespace view {
template <typename> struct view;
}
namespace detail {
struct any_ {
template <typename T> any_(T);
};
using any = any_;
template <typename T> using decay_t = _t<decay<T>>;
}
enum cardinality { infinite };
template <typename> struct range_cardinality;
template <cardinality> struct basic_view {};
template <typename, typename BaseRng,
cardinality = range_cardinality<BaseRng>::value>
struct view_adaptor;
template <typename T> struct static_const { static constexpr T value{}; };
template <typename T>
struct value_type : lazy::if_<int, typename T::value_type> {};
namespace detail {
template <typename...> auto models_(any) -> false_type;
template <typename... Ts, typename Concept,
typename = decltype(Concept().template requires_<Ts...>(Ts()...))>
auto models_(Concept *);
template <typename> struct most_refined_;
template <typename Head, typename... Tail>
struct most_refined_<list<Head, Tail...>> {
using type = Head;
};
template <typename> using avoid_empty_braces = false_type;
}
namespace concepts {
template <typename Concept, typename... Ts>
struct models
: bool_<
_t<decltype(detail::models_<Ts...>(_nullptr_v<Concept>()))>::value> {
};
template <typename Concept, typename... Ts>
auto model_of() -> if_c<models<Concept, Ts...>::value>;
template <typename Concepts, typename... Ts>
struct most_refined : detail::most_refined_<
find_if<Concepts, bind_back<quote<models>, Ts...>>> {
};
struct ConstructibleObject {
template <typename T, if_c<detail::avoid_empty_braces<T>::value, int> = 0>
auto requires_(T);
};
struct SemiRegular {
template <typename T>
auto requires_() -> decltype(model_of<ConstructibleObject, T>);
};
}
template <typename, typename> using ConvertibleTo = concepts::models<int>;
namespace detail {
template <typename T> using tag_elem = back<as_list<T>>;
}
template <typename Base> struct chain { using type = Base; };
template <typename Base>
struct Trans_NS_tagged_detail_tagged : _t<chain<Base>> {};
template <typename Element> struct box {
Element value;
template <typename enable_if<is_default_constructible<Element>::value,
int>::type = 0>
constexpr box() : value{} {}
};
template <typename T, int> using storage = box<T>;
template <typename, typename> struct compressed_tuple_;
template <typename... Ts, long... Is>
struct compressed_tuple_<list<Ts...>, index_sequence<Is...>>
: storage<Ts, 0>... {};
template <typename... Ts>
using compressed_tuple =
compressed_tuple_<list<Ts...>, make_index_sequence<sizeof...(Ts)>>;
template <typename... Ts>
using tagged_compressed_tuple =
Trans_NS_tagged_detail_tagged<compressed_tuple<detail::tag_elem<Ts>>...>;
struct first;
struct compressed_pair : tagged_compressed_tuple<first(int)> {};
struct pipeable_access {
template <typename Pipeable> struct impl : Pipeable {};
};
template <typename Arg, typename Pipe>
auto operator|(Arg arg, Pipe)
-> decltype(pipeable_access::impl<Pipe>::pipe(arg, 0));
struct Readable {
template <typename I> using value_t = _t<value_type<I>>;
};
struct range_access {
template <typename T> static id<box<T>> mixin_base_2_(int);
template <typename Cur>
struct mixin_base_ : decltype(mixin_base_2_<Cur>(0)) {};
template <typename Cur> using mixin_base_t = _t<mixin_base_<Cur>>;
struct Cursor {
template <typename T>
auto requires_()
-> decltype(concepts::model_of<concepts::SemiRegular, mixin_base_t<T>>);
};
template <typename Rng>
static auto begin_cursor(Rng rng, int) -> decltype(rng.begin_cursor());
};
namespace detail {
template <typename T>
using cursor_concept = concepts::most_refined<list<range_access::Cursor>, T>;
template <typename T> using cursor_concept_t = _t<cursor_concept<T>>;
template <typename Cur> struct iterator_associated_types_base {
using cursor_concept_t = detail::cursor_concept_t<Cur>;
using value_type = range_access;
};
}
template <typename Cur>
struct basic_iterator : detail::iterator_associated_types_base<Cur> {};
namespace adl_begin_end_detail {
struct begin_fn {
template <typename Rng> auto impl(Rng rng, int) -> decltype(rng.begin());
template <typename Rng>
auto operator()(Rng rng) -> detail::decay_t<decltype(impl(rng, 0))>;
};
}
auto begin = static_const<begin_fn>::value;
namespace concepts {
struct Range {
template <typename T> using iterator_t = decltype(begin(T()));
};
struct InputRange : Range {
template <typename T> using value_t = Readable::value_t<iterator_t<T>>;
};
}
template <typename Rng>
using range_value_t = concepts::InputRange::value_t<Rng>;
namespace detail {
template <cardinality Card>
integral_constant<cardinality, Card> test_cardinality(basic_view<Card> *);
}
template <typename Rng>
struct range_cardinality
: if_<is_same<Rng, Rng>,
decltype(detail::test_cardinality(static_cast<Rng *>(0)))> {};
namespace detail {
template <typename Rng, typename Cont>
using ConvertibleToContainer =
strict_and<ConvertibleTo<range_value_t<Rng>, Cont>>;
}
}
inline namespace v3 {
template <typename Derived, cardinality Cardinality>
struct view_interface : basic_view<Cardinality> {
template <typename Container, typename D = Derived,
typename enable_if<(detail::ConvertibleToContainer<D, Container>()),
int>::type = 0>
operator Container();
};
namespace detail {
template <typename Derived>
using begin_cursor_t = decltype(range_access::begin_cursor(Derived(), 0));
template <typename Derived>
using facade_iterator_t = basic_iterator<begin_cursor_t<Derived>>;
}
template <typename Derived, cardinality Cardinality>
struct view_facade : view_interface<Derived, Cardinality> {
template <typename D = Derived> detail::facade_iterator_t<D> begin();
};
namespace detail {
template <typename Derived> using begin_adaptor_t = decltype(declval<Derived>);
template <typename Derived>
using adapted_iterator_t = decltype(declval<Derived>);
struct adaptor_value_type_ : compressed_pair {};
}
template <typename, typename>
struct adaptor_cursor : detail::adaptor_value_type_ {};
template <typename D>
using adaptor_cursor_t =
adaptor_cursor<detail::adapted_iterator_t<D>, detail::begin_adaptor_t<D>>;
template <typename Derived, typename, cardinality Cardinality>
struct view_adaptor : view_facade<Derived, Cardinality> {
template <typename D = Derived> adaptor_cursor_t<D> begin_cursor();
};
namespace view {
struct view_access {
template <typename View> struct impl {
template <typename... Ts, typename V = View>
static auto bind(Ts... ts) -> decltype(V::bind(ts...));
};
template <typename Fun> view<Fun> operator()(Fun);
} make_view;
template <typename View> struct view {
View view_;
template <typename Rng, typename Vw>
static auto pipe(Rng rng, Vw) -> decltype(view_(rng));
template <typename... Ts, typename V = View>
auto operator()(Ts...)
-> decltype(make_view(view_access::impl<V>::bind(view_, forward<Ts>...)));
};
}
template <typename Rng>
struct iter_transform_view : view_adaptor<iter_transform_view<Rng>, Rng> {};
namespace view {
struct transform_fn {
template <typename Fun>
static auto bind(transform_fn transform, Fun)
-> decltype(bind(transform, placeholders::_1, 0));
template <typename Rng, typename Fun>
iter_transform_view<Rng> operator()(Rng, Fun);
};
auto transform = static_const<view<transform_fn>>::value;
struct ints_fn : view_facade<int, infinite> {
} ints;
}
}
int m = view::ints | view::transform(0);
}
can be hand reduced to:
template <typename Element> struct box {
Element value;
constexpr box() : value{} {}
};
struct B: box<int> { };
template box<B>::box();
Thanks Markus, that's a great example. I wonder how many new transformations are needed to get to your hand-reduced version.
On 2016-08-09 00:35, octoploid wrote:
Another example (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72457):
Thanks, Markus.
One big missing part in the current C-Reduce is the ability to process some commonly-used C++11 features such as lambda, variadic templates and decltype. I will see what I can do for it when I have spare time.
below is the fully reduced version of test case 00 in this repo:
https://github.com/regehr/compiler-crashes
it seems clear that we have some work to do on simplifying template code (I think we all knew this but I wanted to provide an actionable test in case anyone has time to look into it)