#pragma once #if __has_include() #include #endif #if __has_include() #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "os.hpp" namespace tf { //----------------------------------------------------------------------------- // Traits //----------------------------------------------------------------------------- //// Struct: dependent_false //template //struct dependent_false { // static constexpr bool value = false; //}; // //template //constexpr auto dependent_false_v = dependent_false::value; template inline constexpr bool dependent_false_v = false; // ---------------------------------------------------------------------------- // is_pod //----------------------------------------------------------------------------- template struct is_pod { static const bool value = std::is_trivial_v && std::is_standard_layout_v; }; template constexpr bool is_pod_v = is_pod::value; //----------------------------------------------------------------------------- // NoInit //----------------------------------------------------------------------------- template struct NoInit { //static_assert(is_pod_v, "NoInit only supports POD type"); // constructor without initialization NoInit () noexcept {} // implicit conversion T -> NoInit constexpr NoInit (T value) noexcept : v{value} {} // implicit conversion NoInit -> T constexpr operator T () const noexcept { return v; } T v; }; //----------------------------------------------------------------------------- // Move-On-Copy //----------------------------------------------------------------------------- // Struct: MoveOnCopyWrapper template struct MoC { MoC(T&& rhs) : object(std::move(rhs)) {} MoC(const MoC& other) : object(std::move(other.object)) {} T& get() { return object; } mutable T object; }; template auto make_moc(T&& m) { return MoC(std::forward(m)); } //----------------------------------------------------------------------------- // Visitors. //----------------------------------------------------------------------------- //// Overloadded. //template //struct Visitors : Ts... { // using Ts::operator()... ; //}; // //template //Visitors(Ts...) -> Visitors; // ---------------------------------------------------------------------------- // std::variant // ---------------------------------------------------------------------------- template struct get_index; template struct get_index_impl {}; template struct get_index_impl : std::integral_constant{}; template struct get_index_impl : get_index_impl{}; template struct get_index> : get_index_impl<0, T, Ts...>{}; template constexpr auto get_index_v = get_index::value; // ---------------------------------------------------------------------------- // unwrap_reference // ---------------------------------------------------------------------------- template struct unwrap_reference { using type = T; }; template struct unwrap_reference> { using type = U&; }; template using unwrap_reference_t = typename unwrap_reference::type; template< class T > struct unwrap_ref_decay : unwrap_reference> {}; template using unwrap_ref_decay_t = typename unwrap_ref_decay::type; // ---------------------------------------------------------------------------- // stateful iterators // ---------------------------------------------------------------------------- // STL-styled iterator template struct stateful_iterator { using TB = std::decay_t>; using TE = std::decay_t>; static_assert(std::is_same_v, "decayed iterator types must match"); using type = TB; }; template using stateful_iterator_t = typename stateful_iterator::type; // raw integral index template struct stateful_index { using TB = std::decay_t>; using TE = std::decay_t>; using TS = std::decay_t>; static_assert( std::is_integral_v, "decayed beg index must be an integral type" ); static_assert( std::is_integral_v, "decayed end index must be an integral type" ); static_assert( std::is_integral_v, "decayed step must be an integral type" ); static_assert( std::is_same_v && std::is_same_v, "decayed index and step types must match" ); using type = TB; }; template using stateful_index_t = typename stateful_index::type; // ---------------------------------------------------------------------------- // visit a tuple with a functor at runtime // ---------------------------------------------------------------------------- template void visit_tuple(Func func, Tuple& tup, size_t idx) { if (N == idx) { std::invoke(func, std::get(tup)); return; } if constexpr (N + 1 < std::tuple_size_v) { return visit_tuple(func, tup, idx); } } // ---------------------------------------------------------------------------- // unroll loop // ---------------------------------------------------------------------------- // Template unrolled looping construct. template struct Unroll { template static void eval(F f) { f(beg); Unroll::eval(f); } }; template struct Unroll { template static void eval(F) { } }; template void unroll(F f) { Unroll::eval(f); } // ---------------------------------------------------------------------------- // make types of variant unique // ---------------------------------------------------------------------------- template struct filter_duplicates { using type = T; }; template