Skip to content

Commit

Permalink
✨ (#32)
Browse files Browse the repository at this point in the history
* ✨
+ added is_similar and flatten
+ added _v support for valid and invert
+ updated the corresponding doc

* 💚 ci build fix
  • Loading branch information
bvbasavaraju committed Jan 2, 2024
1 parent 06b72e6 commit a4c430d
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 0 deletions.
41 changes: 41 additions & 0 deletions docs/container/algorithms.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,27 @@ Variants:
* `transform_if_qmf` => when `F` and predicate provided as quoted meta function
* `transform_if_qmf_t` => to avoid `::type`

==== flatten

Usage:
[source, cpp]
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*.
Expand Down Expand Up @@ -971,3 +992,23 @@ then
* `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:
[source, cpp]
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`
4 changes: 4 additions & 0 deletions docs/utility.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ 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 of `C::value`
* `invert_t` => to avoid `::type`
* `invert_v` => to avoid `::value`

=== valid

Expand All @@ -50,8 +52,10 @@ 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

Expand Down
87 changes: 87 additions & 0 deletions include/container/algorithms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1594,4 +1594,91 @@ using sort_qmf_p = sort_p<types, QMF::template fn>;
template <typename types, typename QMF>
using sort_qmf_p_t = typename sort_qmf_p<types, QMF>::type;

//similar
template <typename T1, typename T2>
struct is_similar {
private:
template <typename U1, typename U2>
struct is_similar_impl : public std::false_type {};

template <template <typename...> typename L>
struct is_similar_impl<L<>, L<>> : public std::true_type {};

template <template <typename...> typename L, typename T, typename U>
struct is_similar_impl<L<T>, L<U>> : public std::true_type {};

template <template <typename...> typename L, typename ...Ts>
struct is_similar_impl<L<Ts...>, L<>> : public std::true_type {};

template <template <typename...> typename L, typename ...Ts>
struct is_similar_impl<L<>, L<Ts...>> : public std::true_type {};

template <template <typename...> typename L, typename ...Ts, typename ...Us>
struct is_similar_impl<L<Ts...>, L<Us...>> : public std::true_type {};

public:
using type = std::integral_constant<bool, is_similar_impl<T1, T2>::value>;
};

template <typename T1, typename T2>
using is_similar_t = typename is_similar<T1, T2>::type;

template <typename T1, typename T2>
constexpr static bool is_similar_v = is_similar_t<T1, T2>::value;

// flatten
template <typename types, typename flatten_with = clear_t<types>>
struct flatten {
private:
template <typename P, typename L, typename T>
struct merge_if_similar;

template <template <typename...> typename P, template <typename...> typename L>
struct merge_if_similar<P<>, L<>, L<>> {
using type = P<>;
};

template <template <typename...> typename P, template <typename...> typename L, typename T>
struct merge_if_similar<P<>, L<>, L<T>> {
using type = P<T>;
};

template <template <typename...> typename P, template <typename...> typename L, typename ...Ts>
struct merge_if_similar<P<>, L<>, L<Ts...>> {
using type = P<Ts...>;
};

template <template <typename...> typename P, template <typename...> typename L, typename T>
struct merge_if_similar<P<>, L<>, T> {
using type = P<T>;
};

template <typename L>
struct flatten_impl;

template <template <typename...> typename L>
struct flatten_impl<L<>> {
using type = L<>;
};

template <template <typename...> typename L, typename T>
struct flatten_impl<L<T>> {
using type = typename merge_if_similar<L<>, flatten_with, T>::type;
};

template <template <typename...> typename L, typename T, typename ...Ts>
struct flatten_impl<L<T, Ts...>> {
using first = typename merge_if_similar<L<>, flatten_with, T>::type;
using rest = typename flatten_impl<L<Ts...>>::type;

using type = push_back_t<first, rest>;
};

public:
using type = typename flatten_impl<types>::type;
};

template <typename types, typename flatten_with = clear_t<types>>
using flatten_t = typename flatten<types, flatten_with>::type;

} // namespace ctl
12 changes: 12 additions & 0 deletions include/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@ struct invert_c {
template <bool C>
using invert_c_t = typename invert_c<C>::type;

template <bool C>
constexpr static bool invert_c_v = invert_c_t<C>::value;

template <typename C>
using invert = invert_c<C::value>;

template <typename C>
using invert_t = typename invert<C>::type;

template <typename C>
constexpr static bool invert_v = invert_t<C>::value;

// valid
template <template <typename...> typename F, typename... Ts>
struct valid {
Expand All @@ -43,12 +49,18 @@ struct valid {
template <template <typename...> typename F, typename... Ts>
using valid_t = typename valid<F, Ts...>::type;

template <template <typename...> typename F, typename... Ts>
constexpr static bool valid_v = valid_t<F, Ts...>::value;

template <typename QMF, typename... Ts>
using valid_qmf = valid<QMF::template fn, Ts...>;

template <typename QMF, typename... Ts>
using valid_qmf_t = typename valid_qmf<QMF, Ts...>::type;

template <typename QMF, typename... Ts>
constexpr static bool valid_qmf_v = valid_qmf_t<QMF, Ts...>::value;

// select
template <bool C, typename T, typename F>
struct select_c {
Expand Down
139 changes: 139 additions & 0 deletions test/container/list_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4291,3 +4291,142 @@ TEST_F(list_test, sort_qmf_p) {
EXPECT_FALSE(expect_false);
}
}

TEST_F(list_test, is_similar) {
using L1 = ctl::list<int, char, float>;
using L2 = ctl::list<double>;
using L3 = ctl::list<>;
using L4 = ctl::list<double, ctl::list<>>;
using L5 = ctl::list<double, ctl::list<char>>;

EXPECT_TRUE((ctl::is_similar_v<L1, L2>));
EXPECT_TRUE((ctl::is_similar_v<L1, L3>));
EXPECT_TRUE((ctl::is_similar_v<L1, L4>));
EXPECT_TRUE((ctl::is_similar_v<L1, L5>));
EXPECT_TRUE((ctl::is_similar_v<L2, L3>));
EXPECT_TRUE((ctl::is_similar_v<L2, L4>));
EXPECT_TRUE((ctl::is_similar_v<L2, L5>));
EXPECT_TRUE((ctl::is_similar_v<L3, L4>));
EXPECT_TRUE((ctl::is_similar_v<L3, L5>));
EXPECT_TRUE((ctl::is_similar_v<L4, L5>));

using L6 = std::tuple<int, char, float>;
using L7 = std::tuple<double>;
using L8 = std::tuple<>;
using L9 = std::tuple<double, std::tuple<>>;
using L10 = std::tuple<double, std::tuple<char>>;
using L11 = std::tuple<double, ctl::list<char>>;

EXPECT_TRUE((ctl::is_similar_v<L6, L7>));
EXPECT_TRUE((ctl::is_similar_v<L6, L8>));
EXPECT_TRUE((ctl::is_similar_v<L6, L9>));
EXPECT_TRUE((ctl::is_similar_v<L6, L10>));
EXPECT_TRUE((ctl::is_similar_v<L6, L11>));
EXPECT_TRUE((ctl::is_similar_v<L7, L8>));
EXPECT_TRUE((ctl::is_similar_v<L7, L9>));
EXPECT_TRUE((ctl::is_similar_v<L7, L10>));
EXPECT_TRUE((ctl::is_similar_v<L7, L11>));
EXPECT_TRUE((ctl::is_similar_v<L8, L9>));
EXPECT_TRUE((ctl::is_similar_v<L8, L10>));
EXPECT_TRUE((ctl::is_similar_v<L8, L11>));
EXPECT_TRUE((ctl::is_similar_v<L9, L10>));
EXPECT_TRUE((ctl::is_similar_v<L9, L11>));
EXPECT_TRUE((ctl::is_similar_v<L10, L11>));

EXPECT_FALSE((ctl::is_similar_v<L1, L6>));
EXPECT_FALSE((ctl::is_similar_v<L1, L7>));
EXPECT_FALSE((ctl::is_similar_v<L1, L8>));
EXPECT_FALSE((ctl::is_similar_v<L1, L9>));
EXPECT_FALSE((ctl::is_similar_v<L1, L10>));
EXPECT_FALSE((ctl::is_similar_v<L1, L11>));
EXPECT_FALSE((ctl::is_similar_v<L2, L6>));
EXPECT_FALSE((ctl::is_similar_v<L2, L7>));
EXPECT_FALSE((ctl::is_similar_v<L2, L8>));
EXPECT_FALSE((ctl::is_similar_v<L2, L9>));
EXPECT_FALSE((ctl::is_similar_v<L2, L10>));
EXPECT_FALSE((ctl::is_similar_v<L2, L11>));
EXPECT_FALSE((ctl::is_similar_v<L3, L6>));
EXPECT_FALSE((ctl::is_similar_v<L3, L7>));
EXPECT_FALSE((ctl::is_similar_v<L3, L8>));
EXPECT_FALSE((ctl::is_similar_v<L3, L9>));
EXPECT_FALSE((ctl::is_similar_v<L3, L10>));
EXPECT_FALSE((ctl::is_similar_v<L3, L11>));
EXPECT_FALSE((ctl::is_similar_v<L4, L6>));
EXPECT_FALSE((ctl::is_similar_v<L4, L7>));
EXPECT_FALSE((ctl::is_similar_v<L4, L8>));
EXPECT_FALSE((ctl::is_similar_v<L4, L9>));
EXPECT_FALSE((ctl::is_similar_v<L4, L10>));
EXPECT_FALSE((ctl::is_similar_v<L4, L11>));
EXPECT_FALSE((ctl::is_similar_v<L5, L6>));
EXPECT_FALSE((ctl::is_similar_v<L5, L7>));
EXPECT_FALSE((ctl::is_similar_v<L5, L8>));
EXPECT_FALSE((ctl::is_similar_v<L5, L9>));
EXPECT_FALSE((ctl::is_similar_v<L5, L10>));
EXPECT_FALSE((ctl::is_similar_v<L5, L11>));
}

TEST_F(list_test, flatten) {
// {
// using list = ctl::list<ctl::list<int>>;

// // ctl::debug::show_type<ctl::flatten<list, std::tuple<>>::req>();
// EXPECT_TRUE((std::is_same_v<ctl::flatten_t<list>, ctl::list<int>>));
// // EXPECT_FALSE((std::is_same_v<ctl::flatten_t<list>, list>));
// }
{
using list = ctl::list<double, ctl::list<>>;

EXPECT_TRUE((std::is_same_v<ctl::flatten_t<list>, ctl::list<double>>));
EXPECT_FALSE((std::is_same_v<ctl::flatten_t<list>, list>));
}

{
using list = ctl::list<double, ctl::list<char>>;

EXPECT_TRUE((std::is_same_v<ctl::flatten_t<list>, ctl::list<double, char>>));
EXPECT_FALSE((std::is_same_v<ctl::flatten_t<list>, list>));
}

{
using list = std::tuple<double, std::tuple<>>;

EXPECT_TRUE((std::is_same_v<ctl::flatten_t<list>, std::tuple<double>>));
EXPECT_FALSE((std::is_same_v<ctl::flatten_t<list>, list>));
}

{
using list = std::tuple<double, std::tuple<char>>;

EXPECT_TRUE((std::is_same_v<ctl::flatten_t<list>, std::tuple<double, char>>));
EXPECT_FALSE((std::is_same_v<ctl::flatten_t<list>, list>));
}

{
using list = std::tuple<double, ctl::list<char>>;

EXPECT_TRUE((std::is_same_v<ctl::flatten_t<list>, list>));
EXPECT_FALSE((std::is_same_v<ctl::flatten_t<list>, std::tuple<double, char>>));
}

{
using list = std::tuple<int, std::tuple<>, void, std::tuple<float, double>>;

EXPECT_TRUE((std::is_same_v<ctl::flatten_t<list>, std::tuple<int, void, float, double>>));
EXPECT_FALSE((std::is_same_v<ctl::flatten_t<list>, list>));
}

{
using list = ctl::list<int, ctl::list<float>, std::tuple<void>>;

EXPECT_TRUE((std::is_same_v<ctl::flatten_t<list>, ctl::list<int, float, std::tuple<void>>>));
EXPECT_TRUE((std::is_same_v<ctl::flatten_t<list, std::tuple<>>, ctl::list<int, ctl::list<float>, void>>));
EXPECT_FALSE((std::is_same_v<ctl::flatten_t<list>, list>));
}

{
using list = ctl::list<ctl::list<float>, ctl::list<ctl::list<void>>>;

EXPECT_TRUE((std::is_same_v<ctl::flatten_t<list>, ctl::list<float, ctl::list<void>>>));
EXPECT_FALSE((std::is_same_v<ctl::flatten_t<list>, list>));
}
}
19 changes: 19 additions & 0 deletions test/utils_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,20 @@ TEST_F(utils_test, valid) {
EXPECT_FALSE((ctl::valid_t<member_type, void, int>::value));
EXPECT_TRUE((ctl::valid_t<member_type, int>::value));

EXPECT_FALSE((ctl::valid_v<member_type>));
EXPECT_FALSE((ctl::valid_v<member_type, void>));
EXPECT_FALSE((ctl::valid_v<member_type, void, int>));
EXPECT_TRUE((ctl::valid_v<member_type, int>));

EXPECT_FALSE((ctl::valid_qmf_t<quoted_member_type>::value));
EXPECT_FALSE((ctl::valid_qmf_t<quoted_member_type, void>::value));
EXPECT_FALSE((ctl::valid_qmf_t<quoted_member_type, void, int>::value));
EXPECT_TRUE((ctl::valid_qmf_t<quoted_member_type, int>::value));

EXPECT_FALSE((ctl::valid_qmf_v<quoted_member_type, void>));
EXPECT_FALSE((ctl::valid_qmf_v<quoted_member_type>));
EXPECT_FALSE((ctl::valid_qmf_v<quoted_member_type, void, int>));
EXPECT_TRUE((ctl::valid_qmf_v<quoted_member_type, int>));
}

TEST_F(utils_test, quote) {
Expand Down Expand Up @@ -684,4 +694,13 @@ TEST_F(utils_test, not ) {

EXPECT_TRUE((ctl::invert_c_t<false>::value));
EXPECT_FALSE((ctl::invert_c_t<true>::value));

EXPECT_TRUE((ctl::invert_v<std::integral_constant<bool, false>>));
EXPECT_FALSE((ctl::invert_v<std::integral_constant<bool, true>>));

EXPECT_TRUE((ctl::invert_v<std::false_type>));
EXPECT_FALSE((ctl::invert_v<std::true_type>));

EXPECT_TRUE((ctl::invert_c_v<false>));
EXPECT_FALSE((ctl::invert_c_v<true>));
}

0 comments on commit a4c430d

Please sign in to comment.