Skip to content

kelbon/STTL

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

STTL

stl-like algorithms for TYPES

Firstly: All library works with:

  -- represents a type pack
  template <typename... Ts>
  struct typevec {
    static constexpr inline size_t size = sizeof...(Ts);
  };
  --
  template <typename T>
  concept pack = instance_of<T, typevec>;
 
  -- means 'no such position'
  constexpr inline size_t npos = static_cast<size_t>(-1);
  -- NOT A TYPE! =) type analogue of npos
  using notype;

And some algorithms (such as sort) works with this predicats and projections, They are functional objects, which accept types in std::type_identity wrapper

  namespace types {

    template <typename T>
    concept projection = requires(T value) {
      value(std::type_identity<int>{});
    };

    template <typename F>
    concept unary_predicate = projection<F> && requires(F value) {
      { value(std::type_identity<int>{}) } -> std::convertible_to<bool>;
    };

  }

Utility:

namespace sttl {

  template <typename T>
  constexpr inline bool is_notype_v;

  -- works only for templates without NTTPs and template template parameters
  -- true if type an instance of some template
  template <typename T>
  concept specialization = is_specialization<std::remove_cvref_t<T>>;
  
  -- usage example : void foo(instance_of<std::tuple> auto&&... tpls);
  template <typename T, template <typename...> typename OfWhat>
  concept instance_of = specialization<T> && is_instance_of_v<OfWhat, T>;

  template <typename T, typename... Ts>
  constexpr inline size_t count;

  template <typename T, typename... Ts>
  concept one_of = (std::same_as<T, Ts> || ...);

  template<typename T, typename... Ts>
  concept not_a = !one_of<T, Ts...>;

  // compilation error if types are not unique
  // usage example : enum { _ = assert_unique };
  template<typename... Ts>
  constexpr inline bool assert_unique;

  -- for static asserts of smth like
  template<typename...>
  constexpr inline bool always_false = false; 

}  // namespace sttl

Algorithms:

namespace sttl {

  template <types::unary_predicate auto Pred, typename... Ts>
  constexpr inline size_t count_if;

  template <typename T, typename... Ts>
  constexpr inline bool containts;
 
  -- when you need only to store types without any algorithms
  template <typename...>
  struct typelist {};

  -- returns element I from Ts... and sttl::notype if out of range
  template <size_t I, typename... Ts>
  using try_element_t;

  -- returns element I from Ts... or compilation error of out of range
  template <size_t I, typename... Ts>
  using element_t;

  -- returns index of T or npos if more then one such type OR no such type
  template <typename T, typename... Ts>
  constexpr inline size_t find;

  -- returns index of first T in Ts... or npos if no such type
  template <typename T, typename... Ts>
  constexpr inline size_t find_first;

  -- same as std::all_of/none_of/any_of behavior for empty packs
  template <types::unary_predicate auto Pred, typename... Ts>
  constexpr inline bool all_of;

  template <types::unary_predicate auto Pred, typename... Ts>
  constexpr inline bool atleast_one_of;

  template <types::unary_predicate auto Pred, typename... Ts>
  constexpr inline bool none_of;
  
  -- returns pack with types for which Pred returns true
  template <types::unary_predicate auto Pred, typename... Ts>
  using filter;
  
  -- returns index of last T in pack or npos if no such type
  template <typename T, typename... Ts>
  constexpr inline size_t find_last;

  template<std::int_least64_t Value>
  struct integer_literal : constant<Value> {
    // unary operator-
    consteval auto operator-() const;
    // unary operator+
    consteval auto operator+() const;
  
    template <std::integral T>
    requires (std::in_range<T>(Value))
    constexpr operator T() const;
  };

  // NOT NULLTERMINATED
  template <typename Char, size_t N>
  struct fixed_string {
    using char_type;

    std::array<Char, N> chars;

    fixed_string() = default;
    constexpr fixed_string(const Char (&arr)[N + 1]);
    template<typename Traits>
    constexpr fixed_string(std::array<Char, N> arr);
    static constexpr size_t size();
    constexpr auto begin() const;
    constexpr auto end() const;

    constexpr std::basic_string_view<Char> view() const;
  };

  template <typename Char, size_t N0, size_t N1>
  constexpr fixed_string<Char, N0 + N1> operator+(const fixed_string<Char, N0>& left,
                                                  const fixed_string<Char, N1>& right);
                                                 

  template <fixed_string V>
  struct string_literal {
    static constexpr auto value = V;
    using char_type;
    // comparing as NTTP
    consteval auto operator<=>(string_literal) const;
  };

  namespace types {

    template <typename T, pack P>
    constexpr inline size_t count;

    template <unary_predicate auto Pred, pack P>
    constexpr inline size_t count_if;

    template <typename T, pack P>
    constexpr inline bool containts;
   
    -- returns pack with types for which Pred was true 
    template <unary_predicate auto Pred, pack P>
    using filter;

    -- basic block of many algorithms, see std::rotate
    -- rotate<<int, float, double>, 1> --- double int float
    -- rotate <<int, float, double>, -1> --- float double int
    template <pack P, std::int64_t N>
    using rotate;

    -- see std::all_of/none_of/any_of for behavior on empty packs
    template <pack P, unary_predicate auto Pred>
    constexpr inline bool all_of;

    template <pack P, unary_predicate auto Pred>
    constexpr inline bool atleast_one_of;

    template <pack P, unary_predicate auto Pred>
    constexpr inline bool none_of;
   
    -- returns I th element from pack or sttl::notype if out of range
    template <size_t I, pack P>
    using try_element_t;

    -- returns
    -- template <typename T0, typename T1, size_t I>
    -- struct mismatch_result {
    --   using first = T0;                   // type from first pack, where mismatch was. notype if was not
    --   using second = T1;                  // same as first, but from second pack
    --   static constexpr size_t index = I;  // where mismatch was (npos if no mismatch)
    -- };
    template <pack P0, pack P1>
    using mismatch;
    
    -- returns I th element from P or compilation error if out of range
    template <size_t I, pack P>
    using element_t;

    template <unary_predicate auto Pred, pack P>
    using find_if;

    template <unary_predicate auto Pred, pack P>
    using find_if_not;

    template <typename T, pack P>
    constexpr inline size_t find;

    template <typename T, pack P>
    constexpr inline size_t find_first;
    
    -- returns last type from P or sttl::notype if empty pack
    template <pack P>
    using last_t;

    -- returns first type from P or sttl::notype if empty pack
    template <pack P>
    using first_t;

    -- returns new pack with reversed order of types
    template <pack P>
    using reverse;
    
    -- returns pack without first element or sttl::notype if empty pack
    template <pack T>
    using pop_front;
    
    -- returns pack without last element or sttl::notype if empty pack
    template <pack T>
    using pop_back;
    
    -- returns pack with replaced first element to T or sttl::notype if was empty pack
    template <typename T, pack P>
    using replace_front_with;
    
    -- returns pack with replaced last element to T or sttl::notype if was empty pack
    template <typename T, pack P>
    using replace_back_with;

    -- returns new pack with added T before first
    template <typename T, pack U>
    using push_front;

    -- returns new pack with added T after last
    template <typename T, pack U>
    using push_back;
     
    -- returns index of last T in P or npos if no such type
    template <typename T, pack P>
    constexpr inline size_t find_last;

    template <pack Small, pack Big>
    constexpr inline bool starts_with;

    template <pack Small, pack Big>
    constexpr inline bool ends_with;

    -- returns typevec with types [B; E) indexes from pack P
    template <pack P, size_t B, size_t E = P::size>
    using subrange;

    -- returns typevec with template arguments of T or notype if it is not a specialization
    template <typename T>
    using extract;

    -- returns type which is a specialization of Template with types from P
    template <template <typename...> typename Template, pack P>
    using insert;

    -- returns typevec with all template arguments of specializations Ts...
    -- Example: merge<std::vector<int>, typevec<void>> == typevec<int, std::allocator<int>, void>
    template <specialization... Ts>
    using merge;

    -- one of predefined Projectives for sttl::types::sort
    struct type_to_name;
    -- one of predefined Projectives for sttl::types::sort
    struct type_to_size;

    -- projects type with Proj and sorts projected with Compare, returns sorted pack
    template <pack P, projection Proj = type_to_size, typename Compare = std::less<projected_t<Proj>>>
    using sort;

  }  // namespace types

  template <types::unary_predicate auto Pred, typename... Ts>
  using find_if;

  template <types::unary_predicate auto Pred, typename... Ts>
  using find_if_not;

  template <typename... Ts>
  using reverse;

  template <typename... Ts>
  using last_t;

  -- variant Compile Time, stores one type
  -- can contain references, const and volatile types only when initialized from std::type_identity<T>!
  -- can be visited with sttl::visit_ct
  template <typename... Ts>
  struct variant_ct {
    size_t index_ = npos;

    constexpr variant_ct() = default;

    template <typename T>
    requires(containts<std::remove_cvref_t<T>, Ts...>)
    constexpr variant_ct(T&&);

    template <typename T>
    requires(containts<T, Ts...>)
    constexpr variant_ct(std::type_identity<T>);

    constexpr size_t index() const;
  };

  -- visit for variant_ct
  -- visits with exactly one instanciating (std::visit works in O(N!) instantiating...)
  template <instance_of<variant_ct> auto... Vars, typename F>
  constexpr decltype(auto) visit_ct(F&& foo);

  -- is a MATCHER object, accepts arguments and invokes first Foo, which will accept them.
  -- much faster and readable then many if constexpr
  template <auto... Foos>
  constexpr inline auto pattern_matching;
  
  -- returns first element or sttl::npos for empty pack
  template <typename... Ts>
  using try_first_t = typename try_first<Ts...>::type;

  -- returns first from pack or compilation error if empty pack
  -- faster then try_first
  template <typename T0, typename...>
  using first_t = T0;

  -- just C array alias for you
  -- for better quality of fcn code in 2k22
  template<typename T, size_t N>
  using c_array = T[N];

}  // namespace sttl

-- returns sttl::integer_literal and sttl::string_literal, used to create type from value(literal),
-- each value will generate unique type,
-- used for overloading or as NTTP parameters
-- Example : tuple with overloaded for integer_literal operator[]
-- tuple<A, B, C> val { ... };
-- val[1_] // equal to std::get<1>(val);
template <char... Vals>
consteval sttl::integer_literal operator""_i();
template <sttl::fixed_string L>
consteval sttl::string_literal<L> operator""_s();

About

stl-like algorithms for TYPES

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages