Overview
This is a C++ library, created to include algorithms that can be worked out at compile time.
It uses template meta programming and functional programming techniques to execute many algorithms at compile time on one or more types.
The more work done at compile time, less time to complete the job at run time!
All algorithms/features are wrapped in namespace ctl
Features available to use:
Note:
-
Container algorithms and utility are influenced by Boost::MP11.
This has been started as re-inventing wheel theory and taken personal approach to implement the APIs/Functions that MP11 library supports.
Many of the algorithms are having the same name as mentioned in library MP11. -
_t
next to algorithm name is implemented to avoid using::type
keyword with algorithm -
_c
next to algorithm name is implemented to take constants which are known at compile time (ex: true/false or numbers) -
_f
next to algorithm name is implemented to take template types as template parameter -
_p
next to algorithm name is implemented to take predicate as template parameter (predicate is a template type). It is same as_f
, but_p
is used to make it more clear to read -
_qmf
next to algorithm name is implemented to take Quoted meta functions as template parameter-
_qmf
implementations are using its non_qmf
counterparts
-
-
_v
next to algorithm name is implemented to get the constant value (boolean or number). it is like using::value
on the integral_constant type
Container
There are 2 parts here.
-
List ⇒ the container which holds the type
-
Algorithms ⇒ used with
list
type. Not necessarily withctl::list
but any other compile time list as well. ex:std::tuple
List
It is a container which holds the types. It is an heterogenous container.
To use make sure to add #include <container/list.hpp>
in source file.
There are 3 variants of list
-
clt::list<>
⇒ non-instantiable list -
ctl::ilist<>
⇒ instantiable list -
ctl::clist<>
⇒ instantiable and callable list.
It has many operator over-loadings which can be called at runtime.
Example for the same can be found insrc/main.cpp
file
Many algorithms can be applied on the created list type.
Even algorithms from MP11 can also be used with the list type.
Algorithms
Once the heterogenous list is created, algorithms are required to do some work with that list. like for example, to add new element to existing list, or to retrieve an element, or remove specific entry in the list like or even sorting the types in the list. Just like data structure std::vector<>
(note that std::vector<>
can be used to hold the values of homogenous type at runtime).
These algorithms can be used with any list of types like std::tuple<>. It is not restricted to ctl::list
alone.
To use any algorithms make sure to add #include <container/algorithms.hpp>
in source file.
All algorithms will result in new type
. original type is never modified
Modifiers
Set of algorithms are used to get the new list
from the original list
by adding/removing one or more types.
General usage of the algorithm is:
using modified_type = _algo name_<L<Ts...>, U>::type
where,
-
_ algo name _ ⇒ name of the modifiable algorithms listed below
-
L<Ts…> ⇒ list which has to be modified
-
U ⇒ type of the interest. It could be single type or another list type!
This is optional parameter depending on algorithm. -
::type
⇒ to access the type from the result of the modified list.
If algorithm name is postfixed with_t
then there is no need of using::type
Following are some of modifiable
algorithms (replaced with _ algo name _):
rename
Usage:
using result = ctl::rename<L<Ts...>, Y>::type
if
`L<Ts...> = ctl::list<T1, T2, T3>`
`Y == std::tuple`
then
`result = std::tuple<T2, T3, T1>`
Variants:
-
rename
-
rename_t
⇒ to avoid::type
apply
Usage:
using result = ctl::apply<Y, L<Ts...>>::type
if
`Y == std::tuple`
`L<Ts...> = ctl::list<T1, T2, T3>`
then
`result = std::tuple<T2, T3, T1>`
Variants:
-
apply
⇒ same asrename
but template parameters reversed -
apply_t
⇒ to avoid::type
rotate left
Usage:
using result = rotate_left_c<L<Ts...>, _num_>::type
if
`L<Ts...> = L<T1, T2, T3>`
`_num_ = 1`
then
`result = L<T2, T3, T1>`
Variants:
-
rotate_left_c
-
rotate_left_c_t
⇒ to avoid::type
-
rotate_left
⇒num
is passed as type (It should have::value
to access the member).::type
is needed to access the type -
rotate_left_t
⇒ to avoid::type
rotate right
Usage:
using result = rotate_right_c<L<Ts...>, _num_>::type
if
`L<Ts...> = L<T1, T2, T3>`
`_num_ = 1`
then
`result = L<T3, T1, T2>`
Variants:
-
rotate_right_c
-
rotate_right_c_t
⇒ to avoid::type
-
rotate_right
⇒num
is passed as type (It should have::value
to access the member).::type
is needed to access the result type -
rotate_right_t
⇒ to avoid::type
sort
Usage:
using result = sort<L<Ts...>>::type
if
`L<Ts...> = L<T3, T2, T1>`
then
`result = L<T1, T2, T3>`
where `T1::value <= T2::value <= T3::value`.
Logic used here is Quick sort
.
Variants:
-
sort
-
sort_t
⇒ to avoid::type
-
sort_p
⇒ to provide comparator as predicate to compare 2 types.::type
is needed to access the result type-
comparator
should returntrue
if the first template parameter should be considered before the second template parameter
-
-
sort_p_t
⇒ to avoid::type
-
sort_qmf_p
⇒ to provide comparator predicate as quoted meta function.::type
is needed to access the result type -
sort_qmf_p_t
⇒ to avoid::type
reverse
Usage:
using result = ctl::reverse<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = L<T3, T2, T1>`
Variants:
-
reverse
-
reverse_t
⇒ to avoid::type
replace
Usage:
using result = ctl::replace<L<Ts...>, TR, RW>::type
if
`L<Ts...> = L<T1, T2, T3>`
`TR = T2`
`RW = T4`
then
`result = L<T1, T4, T3>`
Variants:
-
replace
-
replace_t
⇒ to avoid::type
-
replace_at_c
⇒ to replace type at given position (position is a constant).::type
is needed to access the result type -
replace_at_c_t
⇒ to avoid::type
-
replace_at
⇒ to replace type at given position (position is a type,::value
is used to access the constant).::type
is needed to access the result type -
replace_at_t
⇒ to avoid::type
-
replace_if
⇒ to replace all types which results intrue
when passed to given predicate.::type
is needed to access the result type -
replace_if_t
⇒ to avoid::type
-
replace_if_qmf
⇒ predicate passed as quoted meta function.::type
is needed to access the result type -
replace_if_qmf_t
⇒ to avoid::type
push_front
Usage:
using result = ctl::push_front<L<Ts...>, T>::type
if
`L<Ts...> = L<T1, T2, T3>`
`L<T4, T5, T6>`
then
`result = L<T4, T5, T6, T1, T2, T3>`
Variants:
-
push_front
⇒ to push anothertype/list
to front of given list -
push_front_t
⇒ used to avoid::type
push_back
Usage:
using result = ctl::push_back<L<Ts...>, T>::type
if
`L<Ts...> = L<T1, T2, T3>`
`L<T4, T5, T6>`
then
`result = L<T1, T2, T3, T4, T5, T6>`
Variants:
-
push_back
⇒ to push anothertype/list
to back of given list -
push_back_t
⇒ to avoid::type
append
Usage:
using result = ctl::append<L<Ts...>, T>::type
if
`L<Ts...> = L<T1, T2, T3>`
`T = `L<T4, T5, T6>`
then
`result = L<T1, T2, T3, T4, T5, T6>`
Variants:
-
append
⇒ alias topush_back
-
append_t
⇒ alias topush_back_t
pop_front
Usage:
using result = ctl::pop_front<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = L<T2, T3>`
if list provided is empty, then it will result in error
Variants:
-
pop_front
-
pop_front_t
⇒ to avoid::type
pop_back
Usage:
using result = ctl::pop_back<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = L<T1, T2>`
Variants:
-
pop_back
-
pop_back_t
⇒ to avoid::type
insert
Usage:
using result = ctl::insert_c<L<Ts...>, _index_, Us...>::type
if
`L<Ts...> = L<T1, T2, T3>`
`_index_ = 1`
`Us... = U1, U2, U3`
then
`result = L<T1, U1, U2, U3, T2, T3>`
if index should be less than size of the L<Ts…>
. otherwise it will result in compiler error
Variants:
-
insert_c
-
insert_c_t
⇒ to avoid::type
-
insert
⇒ when index passed as type (::value
is used to get the index value).::type
is needed to access the result type -
insert_t
⇒ to avoid::type
repeat
Usage:
using result = ctl::repeat_c<L<Ts...>, _count_>::type
if
`L<Ts...> = L<T1, T2, T3>`
_count_ = 2
then
`result = L<T1, T2, T3, T1, T2, T3>`
if count == 0, then result = L<>
Variants:
-
repeat_c
-
repeat_c_t
⇒ to avoid::type
-
repeat
⇒ when count passed as type (::value
is used to get the count value).::type
is needed to access the result type -
repeat_t
⇒ to avoid::type
clear
Usage:
using result = ctl::repeat_c<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = L<>`
Variants:
-
clear
-
clear_t
⇒ to avoid::type
erase
Usage:
using result = ctl::erase_c<L<Ts...>, _pos1_, _pos2_>::type
if
`L<Ts...> = L<T1, T2, T3>`
_pos1_ == 0
_pos2_ == 1
then
`result = L<T2, T3>`
if condition pos1 < L<Ts…>
⇐ pos2 fails, then results in compiler error.
Variants:
-
erase_c
-
erase_c_t
⇒ to avoid::type
-
erase
⇒ when pos1 and pos2 are passed a types.::type
is needed to access the result type -
erase_t
⇒ to avoid::type
remove
Usage:
using result = ctl::remove_type<L<Ts...>, U>::type
if
`L<Ts...> = L<T1, T2, T3>`
`U = T2`
then
`result = L<T1, T2>`
Variants:
-
remove_type
-
remove_type_t
⇒ to avoid::type
-
remove_if
⇒ whenU
is a predicate. ifP<T>
results intrue
then type is removed.::type
is needed to access the result type -
remove_if_t
⇒ to avoid::type
-
remove_if_qmf
-
remove_if_qmf_t
filter
Usage:
using result = ctl::filter_if<P, L1, L2, ..., Ln>::type
if
`L1 = L1<T1, T2, T3>,
`L2 = L2<T4, T5, T6>`
...
`Ln<Tn, Tn+1, Tn+2>`
`P = P<T2, T5, ..., Tn+1> = true`
then
`result = L<T2>`
Variants:
-
filter_if
-
filter_if_t
⇒ to avoid::type
-
filter_if_qmf
⇒ when predicate is passed as quoted meta function.::type
is needed to access the result type -
filter_if_qmf_t
⇒ to avoid::type
copy_if
Usage:
using result = ctl::copy_if<L<Ts...>, P>::type
if
`L<Ts...> = L<T1, T2, T3>`
`P<T2> = true`
then
`result = L<T2>`
Variants:
-
copy_if
⇒ alias tofilter_if
-
copy_if_t
⇒ to avoid::type
-
copy_if_qmf
⇒ alias tofilter_if_qmf
-
copy_if_qmf_t
⇒ to avoid::type
drop
Usage:
using result = ctl::drop_c<L<Ts...>, _count_>::type
if
`L<Ts...> = L<T1, T2, T3>`
_count_ = 2
then
`result = L<T3>`
if count >= L<Ts…>
size, then result = L<>
Variants:
-
drop_c
-
drop_c_t
⇒ to avoid::type
-
drop
⇒ when count is a type.::type
is needed to access the result type -
drop_t
⇒ to avoid::type
remove_duplicates
Usage:
using result = ctl::remove_duplicates<L<Ts...>>::type
if
`L<Ts...> = L<T1, T1, T2>`
_count_ = 2
then
`result = L<T1, T2>`
Variants:
-
remove_duplicates
-
remove_duplicates_t
⇒ to avoid::type
unique
Usage:
using result = ctl::unique<L<Ts...>>::type
if
`L<Ts...> = L<T1, T1, T2>`
_count_ = 2
then
`result = L<T1, T2>`
Variants:
-
unique
⇒ alias toremove_duplicates
-
unique_t
⇒ to avoid::type
unique_if
Usage:
using result = ctl::unique_if<L<Ts...>, P>::type
if
`L<Ts...> = L<T1, T2, T3>`
`P<T> = T2`
then
`result = L<T1, T2>`
Variants:
-
unique_if
⇒ alias toremove_if
-
unique_if_t
⇒ to avoid::type
-
unique_if_qmf
⇒ alias toremove_if_qmf
-
unique_if_qmf_t
⇒ to avoid::type
transform
Usage:
using result = ctl::transform<F, L1, L2, ..., Ln>::type
if
`L1 = L1<T1, T2, T3>
`L2 = L2<T4, T5, T6> `
...
`Ln<Tn, Tn+1, Tn+2>`
then
`result = L<F<T1, T4, ..., Tn>, F<T2, T5, ..., Tn+1>, F<T3, T6, ..., Tn+2>>`.
where, F is templated type.
Variants:
-
transform
-
transform_t
⇒ to avoid::type
-
transform_qmf
⇒ whenF
is provided as quoted meta function.::type
is needed to access the result type -
transform_qmf_t
⇒ to avoid::type
-
transform_if
⇒ when predicateP
is passed as 3rd template argument.result
will haveF<T>
only whenP<T>
istrue
.::type
is needed to access the result type -
transform_if_t
⇒ to avoid::type
-
transform_if_qmf
⇒ whenF
and predicate provided as quoted meta function -
transform_if_qmf_t
⇒ to avoid::type
flatten
Usage:
using result = ctl::flatten<L1, L2=clear_t<L1>>::type
if
`L1 = L1<T1, T2, std::tuple<T3>>
`L2 = std::tuple<>`
then
`result = L1<T1, T2, T3>
L2
is optional
. If L2
is not provided, then L2
will be assumed as L1<>
Variants:
-
flatten
-
flatten_t
⇒ to avoid::type
Accessors
Set of algorithms are used to retrieve the one or more types from the original list
. In some case conditional retrieval
is possible. These algorithms will result in compiler error if the provided list
is empty.
General usage of the algorithm is:
using result = _algo name_<L<Ts...>, P>::type
where,
-
_ algo name _ ⇒ name of the accessor algorithms listed below
-
L<Ts…> ⇒ list from which one or more type is retrieved
-
P ⇒
predicate/function
which isapplied on each type
to access/retrieve.
It isoptional
, not every algorithm needs this parameter -
::type
⇒ to access the type from the result.
If algorithm name is postfixed with_t
then there is no need of using::type
Following are some of accessor
algorithms (replaced with _ algo name _):
at
Usage:
using result = ctl::at_c<L<Ts...>, _pos_>::type
if
`L<Ts...> = L<T1, T2, T3>`
_pos_ == 2
then
`result = T3`
If condition pos < size of L<Ts…>
then it will result in compiler error
Variants:
-
at_c
-
at_c_t
⇒ to avoid::type
-
at
⇒ when pos is passed as type.::type
is needed to access the result type -
at_t
⇒ to avoid::type
first
Usage:
using result = ctl::first<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = T1`
If list provided is empty, then it will result in compiler error
Variants:
-
first
⇒ to get the first type from the list -
first_t
⇒ to avoid::type
front
Usage:
using result = ctl::front<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = T1`
If list provided is empty, then it will result in compiler error
Variants:
-
front
⇒ alias tofirst
-
front_t
⇒ to avoid::type
last
Usage:
using result = ctl::last<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = T3`
If list provided is empty, then it will result in compiler error
Variants:
-
last
⇒ to get the last type from the list -
last_t
⇒ to avoid::type
back
Usage:
using result = ctl::back<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = T3`
If list provided is empty, then it will result in compiler error
Variants:
-
back
⇒ alias tolast
-
back_t
⇒ to avoid::type
head
Usage:
using result = ctl::head<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = L<T1, T2>`
If list provided is empty, then it will result in compiler error.
If there is only one entry in the list, then result = L<>
Variants:
-
head
-
head_t
⇒ to avoid::type
tail
Usage:
using result = ctl::tail<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = L<T2, T3>`
If list provided is empty, then it will result in compiler error.
If there is only one entry in the list, then result = L<>
Variants:
-
tail
-
tail_t
⇒ to avoid::type
take
Usage:
using result = ctl::take<L<Ts...>, _count_>::type
if
`L<Ts...> = L<T1, T2, T3>`
_count_ = 2,
then
`result = L<T1, T2>`
If count >= size of L<Ts…>
then result = L<Ts…>
Variants:
-
take_c
-
take_c_t
⇒ to avoid::type
-
take
⇒ when count is provided as type.::type
is needed to access the result type -
take_t
⇒ to avoid::type
Miscellaneous
Set of algorithms used for miscellaneous stuffs which are not listed above! like for ex, creating the integer sequence, getting the position of the type in a list, getting the size of the list, etc.
Following are some of algorithms:
size
Usage:
using result = ctl::size<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = std::integral_constant<uint32_t, 3>`
Variants:
-
size
-
size_t
⇒ to avoid::type
-
size_v
⇒ to avoid::value
count
Usage:
using result = ctl::count<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = std::integral_constant<uint32_t, 3>`
Variants:
-
count
⇒ alias tosize
-
count_t
⇒ to avoid::type
-
count_v
⇒ to avoid::value
-
count_if
⇒ whenpredicate P
is passed as second template argument. type will be counted only ifP<T> is true
.::type
is needed to access the result type -
count_if_t
⇒ to avoid::type
-
count_if_v
⇒ to avoid::value
-
count_if_qmf
⇒ whenpredicate
is passed as quoted meta function -
count_if_qmf_t
⇒ to avoid::type
-
count_if_qmf_v
⇒ to avoid::value
empty
Usage:
using result = ctl::empty<L<Ts...>>::type
if
`L<Ts...> = L<T1, T2, T3>`
then
`result = std::false_type`
If L<Ts…> = L<>
then result = std::true_type
Variants:
-
empty
-
empty_t
⇒ to avoid::type
-
empty_v
⇒ to avoid::value
contains
Usage:
using result = ctl::contains<L<Ts...>, U>::type
if
`L<Ts...> = L<T1, T2, T3>`
`U == T2`
then
`result = std::true_type`
If U == T4
then result = std::false_type
Variants:
-
contains
-
contains_t
⇒ to avoid::type
-
contains_v
⇒ to avoid::value
find
Usage:
using result = ctl::find<L<Ts...>, U>::type
if
`L<Ts...> = L<T1, T2, T3>`
`U == T2`
then
`result = std::integral_constant<uint32_t, 1>`.
If U
is not found in list, then result
is size of the list
Variants:
-
find
-
find_t
⇒ to avoid::type
-
find_v
⇒ to avoid::value
-
find_if
⇒ whenU
is a predicate.result
will have the first position for whichP<T>
will result intrue
.::type
is needed to access the result type -
find_if_t
⇒ to avoid::type
-
find_if_v
⇒ to avoid::value
-
find_if_qmf
⇒ when predicate is passed as quoted meta function.::type
is needed to access the result type -
find_if_qmf_t
⇒ to avoid::type
-
find_if_qmf_v
⇒ to avoid::value
all_of
Usage:
using result = ctl::all_of<L<Ts...>, P>::type
if
`L<Ts...> = L<T1, T2, T3>`
`P<T> == true` for all T1, T2, T3 types
then
`result = std::true_type`,
`result = std::false_type`, if P<T> == false for any one of the types
Variants:
-
all_of
-
all_of_t
⇒ to avoid::type
-
all_of_v
⇒ to avoid::value
-
all_of_qmf
⇒ when predicate is passed as quoted meta function.::type
is needed to access the result type -
all_of_qmf_t
⇒ to avoid::type
-
all_of_qmf_v
⇒ to avoid::value
any_of
Usage:
using result = ctl::any_of<L<Ts...>, P>::type
if
`L<Ts...> = L<T1, T2, T3>`
`P<T> == true` for any T1, T2, T3 types
then
`result = std::true_type`,
`result = std::false_type`, if P<T> == false for all types
Variants:
-
any_of
-
any_of_t
⇒ to avoid::type
-
any_of_v
⇒ to avoid::value
-
any_of_qmf
⇒ when predicate is passed as quoted meta function.::type
is needed to access the result type -
any_of_qmf_t
⇒ to avoid::type
-
any_of_qmf_v
⇒ to avoid::value
none_of
Usage:
using result = ctl::none_of<L<Ts...>, P>::type
if
`L<Ts...> = L<T1, T2, T3>`
`P<T> == false` for all T1, T2, T3 types
then
`result = std::true_type`,
`result = std::false_type`, if P<T> for any one of the types
Variants:
-
none_of
-
none_of_t
⇒ to avoid::type
-
none_of_v
⇒ to avoid::value
-
none_of_qmf
⇒ when predicate is passed as quoted meta function.::type
is needed to access the result type -
none_of_qmf_t
⇒ to avoid::type
-
none_of_qmf_v
⇒ to avoid::value
from integer sequence
Usage:
using result = ctl::from_integer_sequence<sequence, RT>::type
if
`sequence = std::integer_sequence<unsigned int, 9, 2, 5>`
`RT == ctl::list`
then
`result = ctl::list<std::integral_constant<unsigned int, 9>, std::integral_constant<unsigned int, 2>, std::integral_constant<unsigned int, 5> >`
RT
default type is std::tuple
.
Variants:
-
from_integer_sequence
-
from_integer_sequence_t
⇒ to avoid::type
iota
Usage:
using result = ctl::iota_c<_count_, DT, RT>::type
if
_count_ = 3,
`DT = uint32_t`
`RT == ctl::list`
then
`result = ctl::list<std::integral_constant<uint32_t, 0>, std::integral_constant<uint32_t, 1>, std::integral_constant<uint32_t, 2> >`
DT
default type is uint32_t
.
RT
default type is std::tuple
.
-
iota_c
-
iota_c_t
⇒ to avoid::type
-
iota
⇒ when count is provided as type.::type
is needed to access the result type -
iota_t
⇒ to avoid::type
is_similar
Usage:
using result = ctl::is_similar<T1, T2>::type
if
T1 = std::tuple<Ts...>,
T2 = std::tuple<Us...>
then
`result = std::integral_constant<bool, true>
if T1 or T2 are not similar list, then result will be false type
-
is_similar
-
is_similar_t
⇒ to avoid::type
-
is_similar_v
⇒ to avoid::value
Utility
Following struct(s)/algorithm(s) can be applied on the types. To use algorithms make sure to add #include <utils.hpp>
in source file.
quote
This helps to wrap template type inside a structure called quote
.
Template type can be accessed with the help of nested type fn
.
template <template <typename...> typename F>
struct quote {
template <typename... Ts>
using fn = F<Ts...>;
};
invert
This helps to invert the provided type/value.
template <bool C>
struct invert_c {
...
};
variants of invert
are:
-
invert_c
-
invert_c_t
⇒ to avoid::type
-
invert_c_v
⇒ to avoid::value
-
invert
⇒ to pass typename as template parameter.
boolean value is accessed with the help ofC::value
-
invert_t
⇒ to avoid::type
-
invert_v
⇒ to avoid::value
valid
This helps to validate if the provided template type is valid or not.
template <template <typename...> typename F, typename... Ts>
struct valid {
...
};
It results in std::true_type
if F<Ts…>::type
is valid. std::false_type
otherwise.
variants of valid
are:
-
valid
-
valid_t
⇒ to avoid using::type
-
valid_v
⇒ to avoid using::value
-
valid_qmf
⇒ to pass template function as a quoted meta function -
valid_qmf_t
⇒ to avoid using::type
-
valid_qmf_v
⇒ to avoid using::value
select
This is equivalent of ternary operator but for types.
template <bool C, typename T, typename F>
struct select_c {
...
};
If condition C
is true
, select_c<>::type will be alias to T
, to F
otherwise.
variants of select
are:
-
select_c
⇒ when condition istrue/false
value.::type
required to retrieve the type -
select_c_t
⇒ to avoid::type
-
select
⇒ when condition is a type.
boolean value is accessed with the help ofC::value
-
select_t
⇒ to avoid::type
Following variants of select is used to get the false type as templated function.
i.e. if condition results in false
then selected type is F<Ts…>
.
template <bool C, typename T, template <typename...> typename F, typename... Ts>
using select_f_c_t {
...
};
-
select_f_c
⇒ when condition istrue/false
value.::type
required to retrieve the type -
select_f_c_t
⇒ to avoid::type
-
select_f
⇒ when condition is a type. boolean value is accessed with the help ofC::value
-
select_f_t
⇒ to avoid::type
-
select_qmf_c
⇒ whenfalse
type is captured with quoted meta function, and condition istrue/false
value -
select_qmf_c_t
⇒ to avoid::type
-
select_qmf
⇒ whenfalse
type is captured with quoted meta function, and condition is a type -
select_qmf_t
⇒ to avoid::type
is_function
This will check if the provided type is a function or not.
template <typename T>
struct is_function {
...
};
If the provided type is not a reference and adding const to type will not result in the const, then it is considered as function.
variants of is_function
are:
-
is_function_t
⇒ to avoid using::type
-
is_function_v
⇒ to avoid using::value
is_invocable
This will check if the provided type is a function
OR a class which implements operator()
template <typename T>
struct is_invocable {
...
};
It makes use of the CPP member detection idiom technique.
If the provided T is a function, then it will result in std::true_type
If the provided T is a class, if it implements operator()
then it will result in std::true_type
otherwise it will result in std::false_type
variants of is_invocable
are:
-
is_invocable_t
⇒ to avoid using::type
-
is_invocable_v
⇒ to avoid using::value