#pragma once /* * Copyright 2018-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #define PUSHMI_NOEXCEPT_AUTO(...) \ noexcept(noexcept(static_cast(__VA_ARGS__)))\ /**/ #define PUSHMI_NOEXCEPT_RETURN(...) \ PUSHMI_NOEXCEPT_AUTO(__VA_ARGS__) {\ return (__VA_ARGS__);\ }\ /**/ namespace pushmi { #if __cpp_fold_expressions >= 201603 template PUSHMI_INLINE_VAR constexpr bool and_v = (Bs && ...); template PUSHMI_INLINE_VAR constexpr bool or_v = (Bs || ...); template PUSHMI_INLINE_VAR constexpr int sum_v = (Is + ...); #else namespace detail { template struct bools; template constexpr int sum_impl(int const (&rgi)[N], int i = 0, int state = 0) noexcept { return i == N ? state : sum_impl(rgi, i + 1, state + rgi[i]); } template constexpr int sum_impl() noexcept { using RGI = int[sizeof...(Is)]; return sum_impl(RGI{Is...}); } } // namespace detail template PUSHMI_INLINE_VAR constexpr bool and_v = PUSHMI_PP_IS_SAME(detail::bools, detail::bools); template PUSHMI_INLINE_VAR constexpr bool or_v = !PUSHMI_PP_IS_SAME( detail::bools, detail::bools); template PUSHMI_INLINE_VAR constexpr int sum_v = detail::sum_impl(); #endif template struct typelist; template using void_t = void; template using remove_cvref_t = std::remove_cv_t>; PUSHMI_CONCEPT_DEF( template(class... Args) (concept True)(Args...), true ); PUSHMI_CONCEPT_DEF( template(class T, template class C) (concept Valid)(T, C), True< C > ); PUSHMI_CONCEPT_DEF( template (class T, template class Trait, class... Args) (concept Satisfies)(T, Trait, Args...), static_cast(Trait::type::value) ); PUSHMI_CONCEPT_DEF( template (class T, class U) concept Same, PUSHMI_PP_IS_SAME(T, U) && PUSHMI_PP_IS_SAME(U, T) ); PUSHMI_CONCEPT_DEF( template (bool...Bs) (concept And)(Bs...), and_v ); PUSHMI_CONCEPT_DEF( template (bool...Bs) (concept Or)(Bs...), or_v ); PUSHMI_CONCEPT_DEF( template (class T) concept Object, requires (T* p) ( *p, implicitly_convertible_to(p) ) ); PUSHMI_CONCEPT_DEF( template (class T, class... Args) (concept Constructible)(T, Args...), PUSHMI_PP_IS_CONSTRUCTIBLE(T, Args...) ); PUSHMI_CONCEPT_DEF( template (class T) concept MoveConstructible, Constructible ); PUSHMI_CONCEPT_DEF( template (class From, class To) concept ConvertibleTo, requires (From (&f)()) ( static_cast(f()) ) && std::is_convertible::value ); PUSHMI_CONCEPT_DEF( template (class A, class B) concept DerivedFrom, __is_base_of(B, A) ); PUSHMI_CONCEPT_DEF( template (class A) concept Decayed, Same> ); PUSHMI_CONCEPT_DEF( template (class T, class U) concept Assignable, requires(T t, U&& u) ( t = (U &&) u, requires_> ) && Same ); PUSHMI_CONCEPT_DEF( template (class T) concept EqualityComparable, requires(remove_cvref_t const & t) ( implicitly_convertible_to( t == t ), implicitly_convertible_to( t != t ) ) ); PUSHMI_CONCEPT_DEF( template (class T) concept SemiMovable, Object && Constructible && ConvertibleTo ); PUSHMI_CONCEPT_DEF( template (class T) concept Movable, SemiMovable && Assignable ); PUSHMI_CONCEPT_DEF( template (class T) concept Copyable, Movable && Assignable && ConvertibleTo ); PUSHMI_CONCEPT_DEF( template (class T) concept Semiregular, Copyable && Constructible ); PUSHMI_CONCEPT_DEF( template (class T) concept Regular, Semiregular && EqualityComparable ); namespace detail { // is_ taken from meta library template class> struct is_ : std::false_type {}; template class C> struct is_, C> : std::true_type {}; template class C> constexpr bool is_v = is_::value; template using requires_ = std::enable_if_t; PUSHMI_INLINE_VAR constexpr struct as_const_fn { template constexpr const T& operator()(T& t) const noexcept { return t; } } const as_const{}; } // namespace detail } // namespace pushmi