https://github.com/zxshady/extra_traits
https://github.com/zxshady/extra_traits
Last synced: 6 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/zxshady/extra_traits
- Owner: ZXShady
- Created: 2024-07-09T05:46:49.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-05T11:35:45.000Z (almost 2 years ago)
- Last Synced: 2025-03-29T23:51:07.567Z (over 1 year ago)
- Language: C++
- Size: 111 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# extra_traits
simple library for some missing type traits I always need when making unreadable meta programs.
Minimum C++11 with support for variadic macros and variaidc templates and type traits library.
all these are available in namespace `zxshady::tmp` and all type traits have _t unconditionally but it also has _v shortcuts if available.
has_operator_*
each of these has their own header for minimizing includes you can look at the file names at `include/zxshady/has_operators/`
| Category | Operator |
|---|---|
| Increment/Decrement | post_increment |
| | pre_decrement |
| | pre_increment |
| | post_increment |
| Unary | dereference |
| | complement |
| | unary_minus |
| | unary_plus |
| Bitwise | bit_and |
| | bit_or |
| | bit_xor |
| | bit_and_assign |
| | bit_or_assign |
| | bit_xor_assign |
| Shift | left_shift |
| | left_shift_assign |
| | right_shift |
| | right_shift_assign |
| Logical | logical_and |
| | logical_not |
| | logical_or |
| Arithmetic | plus |
| | minus |
| | modulus |
| | multiply |
| | divide |
| | plus_assign |
| | minus_assign |
| | modulus_assign |
| | multiply_assign |
| | divide_assign |
| Comparison | equal_to |
| | not_equal_to |
| | less |
| | less_equal |
| | greater |
| | greater_equal |
| Accessors | arrow |
| | subscript |
| | addressof |
| Functor | call |
each has_operator_XXX has 4 static members
```cpp
has_operator_XXX::member; // whether it is a member function
has_operator_XXX::free; // whether it is a free function
has_operator_XXX::overloaded; // equalivent to member || free
has_operator_XXX::value; // whether it has the operator or not
```
simple type aliases
```cpp
template
using index_c = std::integral_constant;
template
using alignof_c = std::integral_constant;
template
using sizeof_c = std::integral_constant;
// this is avaiable in C++17
template
using constant = std::integral_constant;
template
using t_ = typename Trait::type; // shortcut trait
template
constexpr bool v_ = Trait::value; // shortcut variable
_
template
using always_false = std::false_type; (var alias : false_v)
template
using always_true = std::true_type; (var alias: true_v)
template
using type_t = T;
template // since C++14
using is_inheritable = bool_constant && !std::is_final_v >;
template
struct empty_base {};
// does not report true for bool
template
using is_signed_integral = std::bool_constant<
!std::is_same_v> && std::is_integral_v && std::is_signed_v>;
// does not report true for bool
template
using is_unsigned_integral = std::bool_constant> && std::is_integral_v && std::is_unsigned_v>;
```
utility functions
```cpp
as_const(T&) // same as std::as__const
as_volatile(T&)
as_cv(T&)
forward_like(T&)
```
Standard Library Features in previous C++ versions
```cpp
// in "extra_traits/standard_library_features.hpp"
std::disjunction
std::conjunction
std::negation
std::is_null_pointer
std::bool_constant
std::type_identity
std::integer_sequence
std::remove_cvref
std::void_t
std::is_scoped_enum
std::is_bounded_array
std::is_unbounded_array
```
utility traits
```cpp
template
inherit_if::type // if Condition is true then inherit from Base otherwise inherit from empty_base
```
non-short circuiting `disjunction` and `conjunction`
```cpp
and_::value;
or_::value;
```
constructing predicates
```cpp
template class... Predicates>
struct predicate_and;
template class... Predicates>
struct predicate_or;
template class Predicates>
struct predicate_not;
// each one of them has a member called
// 'invoke' that is used like this
using is_const_integer = predicate_and;
static_assert(template is_const_integer::invoke::value);
```
unary traits
```cpp
is_scoped_enum::value
is_unscoped_enum::value
```
modifying traits
```cpp
remove_all_pointers -> int;
remove_all_pointers -> float[];
```
## Qualifications Copying and Maniplating Traits
- from [paper](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1016r0.pdf)
*Note each `copy_xxxxx` trait has a corrosponding `clone_xxxxx` (except `copy_signedness` there is no corrosponding `clone_signedness`)* which is equal to `copy_xxxxx>`*
copy_const<From,To>
Show Table
```cpp
From -> To
const From -> const To
volatile From -> To
const volatile From -> const To
--------------------------------
From& -> To
const From& -> To
volatile From& -> To
const volatile From& -> To
--------------------------------
From&& -> To
const From&& -> To
volatile From&& -> To
const volatile From&& -> To
```
copy_volatile<From,To>
Show Table
```cpp
From -> To
const From -> To
volatile From -> volatile To
const volatile From -> volatile To
--------------------------------
From& -> To
const From& -> To
volatile From& -> To
const volatile From& -> To
--------------------------------
From&& -> To
const From&& -> To
volatile From&& -> To
const volatile From&& -> To
```
## copy_cv
is a short cut for copy_const_t
<From,copy_volatile_t<From,To>>
Show Table
From -> To
const From -> const To
volatile From -> volatile To
const volatile From -> const volatile To
--------------------------------
From& -> To
const From& -> To
volatile From& -> To
const volatile From& -> To
--------------------------------
From&& -> To
const From&& -> To
volatile From&& -> To
const volatile From&& -> To
copy_reference<From,To>
Show Table
# NOTE: this uses reference collapsing rules, which may not be wanted if you do not want it then use `clone_reference`.
```cpp
From -> To
const From -> To
volatile From -> To
const volatile From -> To
--------------------------------
From& -> To&
const From& -> To&
volatile From& -> To&
const volatile From& -> To&
--------------------------------
From&& -> To&&
const From&& -> To&&
volatile From&& -> To&&
const volatile From&& -> To&&
```
## copy_cvref
a short cut for "copy_reference, remove_reference_t\>>>"
copy_pointer<From,To>
Show Table
```cpp
From -> To
const From -> To
volatile From -> To
const volatile From -> To
--------------------------------
From* -> To*
From*const -> To*
From*volatile -> To*
From*const volatile -> To*
```
copy_all_pointers<From,To>
Show Table
```cpp
From -> To
const From -> To
volatile From -> To
const volatile From -> To
--------------------------------
From** -> To**
From**const -> To**
From**volatile -> To**
From**const volatile -> To**
```
copy_signedness<From,To>
Show Table
```cpp
signed From -> signed To
const signed From -> signed To
volatile signed From -> signed To
const volatile signed From -> signed To
--------------------------------
unsigned From -> unsigned To
const unsigned From -> unsigned To
volatile unsigned From -> unsigned To
const volatile unsigned From -> unsigned To
--------------------------------
char -> [to's sign does not change] To
const char -> [to's sign does not change] To
volatile char -> [to's sign does not change] To
const volatile char -> [to's sign does not change] To
```
### least_size_[u]int
gets the smallest unsigned or signed integer type that can hold this value
Show Example (it can differ depending on the size of types)
```cpp
least_size_uint_t<200>; // unsigned char
least_size_int_t<500>; // signed short
```
### remove_[l|r]value_reference
removes the reference qualifier if it is an L or R value respectivly.
Show Table
```cpp
typename remove_lvalue_reference::type; // int
typename remove_lvalue_reference::type; // int
typename remove_lvalue_reference::type; // int&&
typename remove_rvalue_reference::type; // int
typename remove_rvalue_reference::type; // int&
typename remove_rvalue_reference::type; // int
```
### ZXSHADY_FWD ZXSHADY_MOV macros
the first does a std::forward and the second does std::move, why does these exist? well it is for compile time performance as std::forward is relativly expensive for a glorified `static_cast` these macros fix this issue these macros are in the `extra_traits/macros.hpp` header file.
Show Example
```cpp
[](auto&& vals) {
std::forward(vals);
// vs
ZXSHADY_FWD(vals)
std::move(vals);
// vs
ZXSHADY_MOV(vals);
}
```
is_explicitly_constructible
tests for whether the type is explicitly constructible given the Args
*it also has `is_explicitly_default_constructible`,`is_explicitly_copy_constructible` and `is_explicitly_move_constructible`*
```cpp
using namespace zxshady::tmp;
struct A {
explicit A(int,int);
/*implicit*/ A(int,int,int);
};
is_explicitly_constructible::value; // true
is_explicitly_constructible::value; // false
is_explicitly_constructible::value; // false
```
## is_implicitly_constructible
the opposite of [is_explicitly_constructible\](#is_explicitly_constructible) it checks whether the type is implictly constructible
*it also has `is_implicitly_default_constructible`,`is_implicitly_copy_constructible` and `is_implicitly_move_constructible`*
```cpp
using namespace zxshady::tmp;
struct A {
explicit A(int,int);
/*implicit*/ A(int,int,int);
};
is_implicitly_constructible::value; // false
is_implicitly_constructible::value; // true
is_implicitly_constructible::value; // false
```
## type_list
a container that contains types.
## *static members*
size
a static constant equal to `sizeof...(Types)`
```cpp
using List = type_list;
static_assert(List::size == 3);
```
is_empty
a static boolean constant equal to size == 0
```cpp
using List = type_list;
using List2 = type_list<>;
static_assert(!List::is_empty);
static_assert(List2::is_empty);
```
at<Index>
index into the types from the list.
if the index is out of bounds a `static_assert` will fire.
```cpp
using List = type_list;
static_assert(std::is_same_v>);
```
at_or<Index,OrType>
index into the types from the list. if the index is out of bounds
then returns the OrType instead of failing.
```cpp
using List = type_list;
static_assert(std::is_same_v>);
static_assert(std::is_same_v>);
```
front
equal to `List::template at<0>`
*note this member does not exist if is_empty is true*
```cpp
using List = type_list;
static_assert(std::is_same_v);
```
back
equal to `List::template at<size-1>`
*note this member does not exist if is_empty is true*
```cpp
using List = type_list;
static_assert(std::is_same_v);
```
operator+
does concatenation of 2 lists
```cpp
using List1 = type_list;
using List2 = type_list;
static_assert(std::is_same_v);
```
reverse
reverses the list
```cpp
using List = type_list;
using NewList = List::reverse;
static_assert(std::is_same_v);
static_assert(std::is_same_v);
```
pop_front
pops the first type in the list
```cpp
using List = type_list;
using NewList = List::pop_front;
static_assert(std::is_same_v);
```
pop_back
pops the last type in the list
```cpp
using List = type_list;
using NewList = List::pop_back;
static_assert(std::is_same_v);
```
transform<TransformTrait>
apply the TransformTrait to every type in the list,
```cpp
using List = type_list;
static_assert(std::is_same_v,type_list >);
```
rename_to<Template>
```cpp
using List = type_list>;
static_assert(std::is_same_v,std::vector> >);
```
insert<Index,Types...>
```cpp
using List = type_list;
static_assert(std::is_same_v,type_list >);
```
erase<Index>
```cpp
using List = type_list;
static_assert(std::is_same_v,type_list >);
```
erase_if<Predicate>
```cpp
using List = type_list;
static_assert(std::is_same_v,type_list >);
```
slice<Begin,End = size>
```cpp
using List = type_list;
static_assert(std::is_same_v,type_list>);
static_assert(std::is_same_v,type_list>);
static_assert(std::is_same_v,type_list>);
static_assert(std::is_same_v>,type_list<>>);
```
drop_first<Count>
```cpp
using List = type_list;
static_assert(std::is_same_v,type_list>);
static_assert(std::is_same_v,type_list>);
static_assert(std::is_same_v,type_list>);
static_assert(std::is_same_v>,type_list<>>);
```
drop_last<Count>
```cpp
using List = type_list;
static_assert(std::is_same_v,type_list>);
static_assert(std::is_same_v,type_list>);
static_assert(std::is_same_v,type_list>);
static_assert(std::is_same_v>,type_list<>>);
```
replace_at<Index,T>
```cpp
using List = type_list;
static_assert(std::is_same_v, type_list>);
static_assert(std::is_same_v, type_list>);
static_assert(std::is_same_v, type_list>);
```
## Free Functions
find_if<Predicate,Pos = 0>
*note* returns std::size_t(-1) on not found
```cpp
using List = type_list;
static_assert(find_if(List{}) == 2);
static_assert(find_if(List{}) == 3);
```
find<T,Pos = 0>
```cpp
using List = type_list;
static_assert(find(List{}) == std::size_t(-1));
static_assert(find(List{}) == 1);
```
type_list_repeat_n<N,T>
returns a type_list with N Ts in it
```cpp
static_assert(std::is_same_v, type_list>);
static_assert(std::is_same_v, type_list<>>);
static_assert(std::is_same_v, type_list>);
```
there is still more methods.
documentation incomplete...