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. -
_tnext to algorithm name is implemented to avoid using::typekeyword with algorithm -
_cnext to algorithm name is implemented to take constants which are known at compile time (ex: true/false or numbers) -
_fnext to algorithm name is implemented to take template types as template parameter -
_pnext to algorithm name is implemented to take predicate as template parameter (predicate is a template type). It is same as_f, but_pis used to make it more clear to read -
_qmfnext to algorithm name is implemented to take Quoted meta functions as template parameter-
_qmfimplementations are using its non_qmfcounterparts
-
-
_vnext to algorithm name is implemented to get the constant value (boolean or number). it is like using::valueon the integral_constant type
Container
There are 2 parts here.
-
List ⇒ the container which holds the type
-
Algorithms ⇒ used with
listtype. Not necessarily withctl::listbut 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.cppfile
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_tthen 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 asrenamebut 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⇒numis passed as type (It should have::valueto access the member).::typeis 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⇒numis passed as type (It should have::valueto access the member).::typeis 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.::typeis needed to access the result type-
comparatorshould returntrueif 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.::typeis 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).::typeis 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,::valueis used to access the constant).::typeis needed to access the result type -
replace_at_t⇒ to avoid::type -
replace_if⇒ to replace all types which results intruewhen passed to given predicate.::typeis needed to access the result type -
replace_if_t⇒ to avoid::type -
replace_if_qmf⇒ predicate passed as quoted meta function.::typeis 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/listto 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/listto 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 (::valueis used to get the index value).::typeis 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 (::valueis used to get the count value).::typeis 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.::typeis 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⇒ whenUis a predicate. ifP<T>results intruethen type is removed.::typeis 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.::typeis 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.::typeis 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⇒ whenFis provided as quoted meta function.::typeis needed to access the result type -
transform_qmf_t⇒ to avoid::type -
transform_if⇒ when predicatePis passed as 3rd template argument.resultwill haveF<T>only whenP<T>istrue.::typeis needed to access the result type -
transform_if_t⇒ to avoid::type -
transform_if_qmf⇒ whenFand 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/functionwhich isapplied on each typeto access/retrieve.
It isoptional, not every algorithm needs this parameter -
::type⇒ to access the type from the result.
If algorithm name is postfixed with_tthen 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.::typeis 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.::typeis 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 Pis passed as second template argument. type will be counted only ifP<T> is true.::typeis needed to access the result type -
count_if_t⇒ to avoid::type -
count_if_v⇒ to avoid::value -
count_if_qmf⇒ whenpredicateis 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⇒ whenUis a predicate.resultwill have the first position for whichP<T>will result intrue.::typeis 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.::typeis 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.::typeis 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.::typeis 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.::typeis 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 ctl::list.
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 ctl::list.
-
iota_c -
iota_c_t⇒ to avoid::type -
iota⇒ when count is provided as type.::typeis 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
equal
Usage:
using result = ctl::equal<T1, T2>::type
if
T1 = std::tuple<Ts...>,
T2 = std::tuple<Ts...>
then
`result = std::integral_constant<bool, true>
if T1 or T2 are not similar list or any entry in the list is not same or list are of different length, then result will be false type
-
equal -
equal_t⇒ to avoid::type -
equal_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
is_same
This helps to Check if the given 2 types are same
template <typename T1, typename T2>
struct is_same {
...
};
It results in std::true_type if T1 and T2 are same. std::false_type otherwise.
variants of is_same are:
-
is_same -
is_same_t⇒ to avoid using::type -
is_same_v⇒ to avoid using::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/falsevalue.::typerequired 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/falsevalue.::typerequired 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⇒ whenfalsetype is captured with quoted meta function, and condition istrue/falsevalue -
select_qmf_c_t⇒ to avoid::type -
select_qmf⇒ whenfalsetype 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