From 8b12832172d3251d92a17f390eb845370a437e37 Mon Sep 17 00:00:00 2001 From: Merry Date: Tue, 19 Apr 2022 11:16:33 +0100 Subject: [PATCH] Import mp --- .gitignore | 1 + include/mcl/mp/metafunction/apply.hpp | 25 +++++ include/mcl/mp/metafunction/bind.hpp | 18 +++ include/mcl/mp/metafunction/identity.hpp | 22 ++++ include/mcl/mp/metafunction/map.hpp | 25 +++++ include/mcl/mp/metavalue/bit_and.hpp | 19 ++++ include/mcl/mp/metavalue/bit_not.hpp | 19 ++++ include/mcl/mp/metavalue/bit_or.hpp | 19 ++++ include/mcl/mp/metavalue/bit_xor.hpp | 19 ++++ include/mcl/mp/metavalue/conjunction.hpp | 42 +++++++ include/mcl/mp/metavalue/disjunction.hpp | 42 +++++++ include/mcl/mp/metavalue/lift_value.hpp | 15 +++ include/mcl/mp/metavalue/logic_and.hpp | 19 ++++ include/mcl/mp/metavalue/logic_if.hpp | 21 ++++ include/mcl/mp/metavalue/logic_not.hpp | 19 ++++ include/mcl/mp/metavalue/logic_or.hpp | 19 ++++ include/mcl/mp/metavalue/product.hpp | 19 ++++ include/mcl/mp/metavalue/sum.hpp | 19 ++++ include/mcl/mp/metavalue/value.hpp | 30 +++++ include/mcl/mp/metavalue/value_cast.hpp | 15 +++ include/mcl/mp/metavalue/value_equal.hpp | 15 +++ include/mcl/mp/misc/argument_count.hpp | 19 ++++ include/mcl/mp/typelist/append.hpp | 25 +++++ include/mcl/mp/typelist/cartesian_product.hpp | 47 ++++++++ include/mcl/mp/typelist/concat.hpp | 94 ++++++++++++++++ include/mcl/mp/typelist/contains.hpp | 23 ++++ include/mcl/mp/typelist/drop.hpp | 33 ++++++ include/mcl/mp/typelist/get.hpp | 18 +++ include/mcl/mp/typelist/head.hpp | 25 +++++ include/mcl/mp/typelist/length.hpp | 20 ++++ include/mcl/mp/typelist/lift_sequence.hpp | 29 +++++ include/mcl/mp/typelist/list.hpp | 13 +++ include/mcl/mp/typelist/lower_to_tuple.hpp | 24 ++++ include/mcl/mp/typelist/prepend.hpp | 25 +++++ include/mcl/mp/typelist/tail.hpp | 25 +++++ include/mcl/scope_exit.hpp | 2 +- include/mcl/type_traits/function_info.hpp | 70 ++++++++++++ include/mcl/type_traits/integer_of_size.hpp | 48 ++++++++ .../type_traits/is_instance_of_template.hpp | 22 ++++ src/CMakeLists.txt | 40 ++++++- tests/CMakeLists.txt | 3 + tests/mp/metavalue_tests.cpp | 90 +++++++++++++++ tests/mp/typelist_tests.cpp | 104 ++++++++++++++++++ tests/type_traits/type_traits_tests.cpp | 39 +++++++ 44 files changed, 1278 insertions(+), 2 deletions(-) create mode 100644 include/mcl/mp/metafunction/apply.hpp create mode 100644 include/mcl/mp/metafunction/bind.hpp create mode 100644 include/mcl/mp/metafunction/identity.hpp create mode 100644 include/mcl/mp/metafunction/map.hpp create mode 100644 include/mcl/mp/metavalue/bit_and.hpp create mode 100644 include/mcl/mp/metavalue/bit_not.hpp create mode 100644 include/mcl/mp/metavalue/bit_or.hpp create mode 100644 include/mcl/mp/metavalue/bit_xor.hpp create mode 100644 include/mcl/mp/metavalue/conjunction.hpp create mode 100644 include/mcl/mp/metavalue/disjunction.hpp create mode 100644 include/mcl/mp/metavalue/lift_value.hpp create mode 100644 include/mcl/mp/metavalue/logic_and.hpp create mode 100644 include/mcl/mp/metavalue/logic_if.hpp create mode 100644 include/mcl/mp/metavalue/logic_not.hpp create mode 100644 include/mcl/mp/metavalue/logic_or.hpp create mode 100644 include/mcl/mp/metavalue/product.hpp create mode 100644 include/mcl/mp/metavalue/sum.hpp create mode 100644 include/mcl/mp/metavalue/value.hpp create mode 100644 include/mcl/mp/metavalue/value_cast.hpp create mode 100644 include/mcl/mp/metavalue/value_equal.hpp create mode 100644 include/mcl/mp/misc/argument_count.hpp create mode 100644 include/mcl/mp/typelist/append.hpp create mode 100644 include/mcl/mp/typelist/cartesian_product.hpp create mode 100644 include/mcl/mp/typelist/concat.hpp create mode 100644 include/mcl/mp/typelist/contains.hpp create mode 100644 include/mcl/mp/typelist/drop.hpp create mode 100644 include/mcl/mp/typelist/get.hpp create mode 100644 include/mcl/mp/typelist/head.hpp create mode 100644 include/mcl/mp/typelist/length.hpp create mode 100644 include/mcl/mp/typelist/lift_sequence.hpp create mode 100644 include/mcl/mp/typelist/list.hpp create mode 100644 include/mcl/mp/typelist/lower_to_tuple.hpp create mode 100644 include/mcl/mp/typelist/prepend.hpp create mode 100644 include/mcl/mp/typelist/tail.hpp create mode 100644 include/mcl/type_traits/function_info.hpp create mode 100644 include/mcl/type_traits/integer_of_size.hpp create mode 100644 include/mcl/type_traits/is_instance_of_template.hpp create mode 100644 tests/mp/metavalue_tests.cpp create mode 100644 tests/mp/typelist_tests.cpp create mode 100644 tests/type_traits/type_traits_tests.cpp diff --git a/.gitignore b/.gitignore index 468d90c..547b4ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *build*/ +.DS_Store diff --git a/include/mcl/mp/metafunction/apply.hpp b/include/mcl/mp/metafunction/apply.hpp new file mode 100644 index 0000000..e2c1714 --- /dev/null +++ b/include/mcl/mp/metafunction/apply.hpp @@ -0,0 +1,25 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +namespace mcl::mp { + +namespace detail { + +template class F, class L> +struct apply_impl; + +template class F, template class LT, class... Es> +struct apply_impl> { + using type = F; +}; + +} // namespace detail + +/// Invokes metafunction F where the arguments are all the members of list L +template class F, class L> +using apply = typename detail::apply_impl::type; + +} // namespace mcl::mp diff --git a/include/mcl/mp/metafunction/bind.hpp b/include/mcl/mp/metafunction/bind.hpp new file mode 100644 index 0000000..2701fc9 --- /dev/null +++ b/include/mcl/mp/metafunction/bind.hpp @@ -0,0 +1,18 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +namespace mcl::mp { + +/// Binds the first sizeof...(A) arguments of metafunction F with arguments A +template class F, class... As> +struct bind { + template + using type = F; +}; + +} // namespace mcl::mp + +#define MCL_MP_BIND(...) ::mcl::mp::bind<__VA_ARGS__>::template type diff --git a/include/mcl/mp/metafunction/identity.hpp b/include/mcl/mp/metafunction/identity.hpp new file mode 100644 index 0000000..737f9ce --- /dev/null +++ b/include/mcl/mp/metafunction/identity.hpp @@ -0,0 +1,22 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +namespace mcl::mp { + +namespace detail { + +template +struct identity_impl { + using type = T; +}; + +} // namespace detail + +/// Identity metafunction +template +using identity = typename identity_impl::type; + +} // namespace mcl::mp diff --git a/include/mcl/mp/metafunction/map.hpp b/include/mcl/mp/metafunction/map.hpp new file mode 100644 index 0000000..13fcaec --- /dev/null +++ b/include/mcl/mp/metafunction/map.hpp @@ -0,0 +1,25 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +namespace mcl::mp { + +namespace detail { + +template class F, class L> +struct map_impl; + +template class F, template class LT, class... Es> +struct map_impl> { + using type = LT...>; +}; + +} // namespace detail + +/// Applies each element of list L to metafunction F +template class F, class L> +using map = typename detail::map_impl::type; + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/bit_and.hpp b/include/mcl/mp/metavalue/bit_and.hpp new file mode 100644 index 0000000..e4a98e2 --- /dev/null +++ b/include/mcl/mp/metavalue/bit_and.hpp @@ -0,0 +1,19 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/lift_value.hpp" + +namespace mcl::mp { + +/// Bitwise and of metavalues Vs +template +using bit_and = lift_value<(Vs::value & ...)>; + +/// Bitwise and of metavalues Vs +template +constexpr auto bit_and_v = (Vs::value & ...); + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/bit_not.hpp b/include/mcl/mp/metavalue/bit_not.hpp new file mode 100644 index 0000000..5d31956 --- /dev/null +++ b/include/mcl/mp/metavalue/bit_not.hpp @@ -0,0 +1,19 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/lift_value.hpp" + +namespace mcl::mp { + +/// Bitwise not of metavalue V +template +using bit_not = lift_value<~V::value>; + +/// Bitwise not of metavalue V +template +constexpr auto bit_not_v = ~V::value; + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/bit_or.hpp b/include/mcl/mp/metavalue/bit_or.hpp new file mode 100644 index 0000000..812edfb --- /dev/null +++ b/include/mcl/mp/metavalue/bit_or.hpp @@ -0,0 +1,19 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/lift_value.hpp" + +namespace mcl::mp { + +/// Bitwise or of metavalues Vs +template +using bit_or = lift_value<(Vs::value | ...)>; + +/// Bitwise or of metavalues Vs +template +constexpr auto bit_or_v = (Vs::value | ...); + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/bit_xor.hpp b/include/mcl/mp/metavalue/bit_xor.hpp new file mode 100644 index 0000000..9c543d4 --- /dev/null +++ b/include/mcl/mp/metavalue/bit_xor.hpp @@ -0,0 +1,19 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/lift_value.hpp" + +namespace mcl::mp { + +/// Bitwise xor of metavalues Vs +template +using bit_xor = lift_value<(Vs::value ^ ...)>; + +/// Bitwise xor of metavalues Vs +template +constexpr auto bit_xor_v = (Vs::value ^ ...); + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/conjunction.hpp b/include/mcl/mp/metavalue/conjunction.hpp new file mode 100644 index 0000000..71a8f67 --- /dev/null +++ b/include/mcl/mp/metavalue/conjunction.hpp @@ -0,0 +1,42 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/logic_if.hpp" +#include "mcl/mp/metavalue/value.hpp" + +namespace mcl::mp { + +namespace detail { + +template +struct conjunction_impl; + +template<> +struct conjunction_impl<> { + using type = false_type; +}; + +template +struct conjunction_impl { + using type = V; +}; + +template +struct conjunction_impl { + using type = logic_if::type, V1>; +}; + +} // namespace detail + +/// Conjunction of metavalues Vs with short-circuiting and type preservation. +template +using conjunction = typename detail::conjunction_impl::type; + +/// Conjunction of metavalues Vs with short-circuiting and type preservation. +template +constexpr auto conjunction_v = conjunction::value; + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/disjunction.hpp b/include/mcl/mp/metavalue/disjunction.hpp new file mode 100644 index 0000000..679a44f --- /dev/null +++ b/include/mcl/mp/metavalue/disjunction.hpp @@ -0,0 +1,42 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/logic_if.hpp" +#include "mcl/mp/metavalue/value.hpp" + +namespace mcl::mp { + +namespace detail { + +template +struct disjunction_impl; + +template<> +struct disjunction_impl<> { + using type = false_type; +}; + +template +struct disjunction_impl { + using type = V; +}; + +template +struct disjunction_impl { + using type = logic_if::type>; +}; + +} // namespace detail + +/// Disjunction of metavalues Vs with short-circuiting and type preservation. +template +using disjunction = typename detail::disjunction_impl::type; + +/// Disjunction of metavalues Vs with short-circuiting and type preservation. +template +constexpr auto disjunction_v = disjunction::value; + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/lift_value.hpp b/include/mcl/mp/metavalue/lift_value.hpp new file mode 100644 index 0000000..bd5df32 --- /dev/null +++ b/include/mcl/mp/metavalue/lift_value.hpp @@ -0,0 +1,15 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +namespace mcl::mp { + +/// Lifts a value into a type (a metavalue) +template +using lift_value = std::integral_constant; + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/logic_and.hpp b/include/mcl/mp/metavalue/logic_and.hpp new file mode 100644 index 0000000..81c40a4 --- /dev/null +++ b/include/mcl/mp/metavalue/logic_and.hpp @@ -0,0 +1,19 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/value.hpp" + +namespace mcl::mp { + +/// Logical conjunction of metavalues Vs without short-circuiting or type presevation. +template +using logic_and = bool_value<(true && ... && Vs::value)>; + +/// Logical conjunction of metavalues Vs without short-circuiting or type presevation. +template +constexpr bool logic_and_v = (true && ... && Vs::value); + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/logic_if.hpp b/include/mcl/mp/metavalue/logic_if.hpp new file mode 100644 index 0000000..b300d26 --- /dev/null +++ b/include/mcl/mp/metavalue/logic_if.hpp @@ -0,0 +1,21 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "mcl/mp/metavalue/value.hpp" + +namespace mcl::mp { + +/// Conditionally select between types T and F based on boolean metavalue V +template +using logic_if = std::conditional_t; + +/// Conditionally select between metavalues T and F based on boolean metavalue V +template +constexpr auto logic_if_v = logic_if::value; + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/logic_not.hpp b/include/mcl/mp/metavalue/logic_not.hpp new file mode 100644 index 0000000..a7a6aee --- /dev/null +++ b/include/mcl/mp/metavalue/logic_not.hpp @@ -0,0 +1,19 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/value.hpp" + +namespace mcl::mp { + +/// Logical negation of metavalue V. +template +using logic_not = bool_value; + +/// Logical negation of metavalue V. +template +constexpr bool logic_not_v = !bool(V::value); + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/logic_or.hpp b/include/mcl/mp/metavalue/logic_or.hpp new file mode 100644 index 0000000..3b46fa5 --- /dev/null +++ b/include/mcl/mp/metavalue/logic_or.hpp @@ -0,0 +1,19 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/value.hpp" + +namespace mcl::mp { + +/// Logical disjunction of metavalues Vs without short-circuiting or type presevation. +template +using logic_or = bool_value<(false || ... || Vs::value)>; + +/// Logical disjunction of metavalues Vs without short-circuiting or type presevation. +template +constexpr bool logic_or_v = (false || ... || Vs::value); + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/product.hpp b/include/mcl/mp/metavalue/product.hpp new file mode 100644 index 0000000..d40c0ce --- /dev/null +++ b/include/mcl/mp/metavalue/product.hpp @@ -0,0 +1,19 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/lift_value.hpp" + +namespace mcl::mp { + +/// Product of metavalues Vs +template +using product = lift_value<(Vs::value * ...)>; + +/// Product of metavalues Vs +template +constexpr auto product_v = (Vs::value * ...); + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/sum.hpp b/include/mcl/mp/metavalue/sum.hpp new file mode 100644 index 0000000..7111c02 --- /dev/null +++ b/include/mcl/mp/metavalue/sum.hpp @@ -0,0 +1,19 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/lift_value.hpp" + +namespace mcl::mp { + +/// Sum of metavalues Vs +template +using sum = lift_value<(Vs::value + ...)>; + +/// Sum of metavalues Vs +template +constexpr auto sum_v = (Vs::value + ...); + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/value.hpp b/include/mcl/mp/metavalue/value.hpp new file mode 100644 index 0000000..693169d --- /dev/null +++ b/include/mcl/mp/metavalue/value.hpp @@ -0,0 +1,30 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +namespace mcl::mp { + +/// A metavalue (of type VT and value v). +template +using value = std::integral_constant; + +/// A metavalue of type size_t (and value v). +template +using size_value = value; + +/// A metavalue of type bool (and value v). (Aliases to std::bool_constant.) +template +using bool_value = value; + +/// true metavalue (Aliases to std::true_type). +using true_type = bool_value; + +/// false metavalue (Aliases to std::false_type). +using false_type = bool_value; + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/value_cast.hpp b/include/mcl/mp/metavalue/value_cast.hpp new file mode 100644 index 0000000..3b88ed7 --- /dev/null +++ b/include/mcl/mp/metavalue/value_cast.hpp @@ -0,0 +1,15 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +namespace mcl::mp { + +/// Casts a metavalue from one type to another +template +using value_cast = std::integral_constant(V::value)>; + +} // namespace mcl::mp diff --git a/include/mcl/mp/metavalue/value_equal.hpp b/include/mcl/mp/metavalue/value_equal.hpp new file mode 100644 index 0000000..a10e07f --- /dev/null +++ b/include/mcl/mp/metavalue/value_equal.hpp @@ -0,0 +1,15 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +namespace mcl::mp { + +/// Do two metavalues contain the same value? +template +using value_equal = std::bool_constant; + +} // namespace mcl::mp diff --git a/include/mcl/mp/misc/argument_count.hpp b/include/mcl/mp/misc/argument_count.hpp new file mode 100644 index 0000000..5a30f49 --- /dev/null +++ b/include/mcl/mp/misc/argument_count.hpp @@ -0,0 +1,19 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/lift_value.hpp" + +namespace mcl::mp { + +/// Metafunction that returns the number of arguments it has +template +using argument_count = lift_value; + +/// Metafunction that returns the number of arguments it has +template +constexpr auto argument_count_v = sizeof...(Ts); + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/append.hpp b/include/mcl/mp/typelist/append.hpp new file mode 100644 index 0000000..838b9c9 --- /dev/null +++ b/include/mcl/mp/typelist/append.hpp @@ -0,0 +1,25 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +namespace mcl::mp { + +namespace detail { + +template +struct append_impl; + +template class LT, class... E1s, class... E2s> +struct append_impl, E2s...> { + using type = LT; +}; + +} // namespace detail + +/// Append items E to list L +template +using append = typename detail::append_impl::type; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/cartesian_product.hpp b/include/mcl/mp/typelist/cartesian_product.hpp new file mode 100644 index 0000000..1b378c6 --- /dev/null +++ b/include/mcl/mp/typelist/cartesian_product.hpp @@ -0,0 +1,47 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metafunction/bind.hpp" +#include "mcl/mp/metafunction/map.hpp" +#include "mcl/mp/typelist/append.hpp" +#include "mcl/mp/typelist/concat.hpp" +#include "mcl/mp/typelist/list.hpp" + +namespace mcl::mp { + +namespace detail { + +template +struct cartesian_product_impl; + +template +struct cartesian_product_impl { + using type = RL; +}; + +template class LT, class... REs, class... E2s> +struct cartesian_product_impl, LT> { + using type = concat< + map>...>; +}; + +template +struct cartesian_product_impl { + using type = typename cartesian_product_impl< + typename cartesian_product_impl::type, + L3, + Ls...>::type; +}; + +} // namespace detail + +/// Produces the cartesian product of a set of lists +/// For example: +/// cartesian_product, list> == list, list, list, list +template +using cartesian_product = typename detail::cartesian_product_impl, Ls...>::type; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/concat.hpp b/include/mcl/mp/typelist/concat.hpp new file mode 100644 index 0000000..cfdefbc --- /dev/null +++ b/include/mcl/mp/typelist/concat.hpp @@ -0,0 +1,94 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/typelist/list.hpp" + +namespace mcl::mp { + +namespace detail { + +template +struct concat_impl; + +template<> +struct concat_impl<> { + using type = list<>; +}; + +template +struct concat_impl { + using type = L; +}; + +template class LT, class... E1s, class... E2s, class... Ls> +struct concat_impl, LT, Ls...> { + using type = typename concat_impl, Ls...>::type; +}; + +template class LT, + class... E1s, + class... E2s, + class... E3s, + class... E4s, + class... E5s, + class... E6s, + class... E7s, + class... E8s, + class... E9s, + class... E10s, + class... E11s, + class... E12s, + class... E13s, + class... E14s, + class... E15s, + class... E16s, + class... Ls> +struct concat_impl< + LT, + LT, + LT, + LT, + LT, + LT, + LT, + LT, + LT, + LT, + LT, + LT, + LT, + LT, + LT, + LT, + Ls...> { + using type = typename concat_impl< + LT< + E1s..., + E2s..., + E3s..., + E4s..., + E5s..., + E6s..., + E7s..., + E8s..., + E9s..., + E10s..., + E11s..., + E12s..., + E13s..., + E14s..., + E15s..., + E16s...>, + Ls...>::type; +}; + +} // namespace detail + +/// Concatenate lists together +template +using concat = typename detail::concat_impl::type; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/contains.hpp b/include/mcl/mp/typelist/contains.hpp new file mode 100644 index 0000000..f8d1fbf --- /dev/null +++ b/include/mcl/mp/typelist/contains.hpp @@ -0,0 +1,23 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/value.hpp" + +namespace mcl::mp { + +/// Does list L contain an element which is same as type T? +template +struct contains; + +template class LT, class... Ts, class T> +struct contains, T> + : bool_value<(false || ... || std::is_same_v)> {}; + +/// Does list L contain an element which is same as type T? +template +constexpr bool contains_v = contains::value; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/drop.hpp b/include/mcl/mp/typelist/drop.hpp new file mode 100644 index 0000000..9c7be44 --- /dev/null +++ b/include/mcl/mp/typelist/drop.hpp @@ -0,0 +1,33 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +namespace mcl::mp { + +namespace detail { + +template +struct drop_impl; + +template class LT> +struct drop_impl> { + using type = LT<>; +}; + +template class LT, class E1, class... Es> +struct drop_impl> { + using type = std::conditional_t, typename drop_impl>::type>; +}; + +} // namespace detail + +/// Drops the first N elements of list L +template +using drop = typename detail::drop_impl::type; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/get.hpp b/include/mcl/mp/typelist/get.hpp new file mode 100644 index 0000000..a2ec746 --- /dev/null +++ b/include/mcl/mp/typelist/get.hpp @@ -0,0 +1,18 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "mcl/mp/metafunction/apply.hpp" + +namespace mcl::mp { + +/// Get element I from list L +template +using get = std::tuple_element_t>; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/head.hpp b/include/mcl/mp/typelist/head.hpp new file mode 100644 index 0000000..6306282 --- /dev/null +++ b/include/mcl/mp/typelist/head.hpp @@ -0,0 +1,25 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +namespace mcl::mp { + +namespace detail { + +template +struct head_impl; + +template class LT, class E1, class... Es> +struct head_impl> { + using type = E1; +}; + +} // namespace detail + +/// Gets the tail/cdr/all-but-the-first-element of list L +template +using head = typename detail::head_impl::type; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/length.hpp b/include/mcl/mp/typelist/length.hpp new file mode 100644 index 0000000..d594960 --- /dev/null +++ b/include/mcl/mp/typelist/length.hpp @@ -0,0 +1,20 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metafunction/apply.hpp" +#include "mcl/mp/misc/argument_count.hpp" + +namespace mcl::mp { + +/// Length of list L +template +using length = apply; + +/// Length of list L +template +constexpr auto length_v = length::value; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/lift_sequence.hpp b/include/mcl/mp/typelist/lift_sequence.hpp new file mode 100644 index 0000000..ba2617b --- /dev/null +++ b/include/mcl/mp/typelist/lift_sequence.hpp @@ -0,0 +1,29 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "mcl/mp/typelist/list.hpp" + +namespace mcl::mp { + +namespace detail { + +template +struct lift_sequence_impl; + +template class VLT, T... values> +struct lift_sequence_impl> { + using type = list...>; +}; + +} // namespace detail + +/// Lifts values in value list VL to create a type list. +template +using lift_sequence = typename detail::lift_sequence_impl::type; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/list.hpp b/include/mcl/mp/typelist/list.hpp new file mode 100644 index 0000000..48348ec --- /dev/null +++ b/include/mcl/mp/typelist/list.hpp @@ -0,0 +1,13 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +namespace mcl::mp { + +/// Contains a list of types +template +struct list {}; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/lower_to_tuple.hpp b/include/mcl/mp/typelist/lower_to_tuple.hpp new file mode 100644 index 0000000..a9007f3 --- /dev/null +++ b/include/mcl/mp/typelist/lower_to_tuple.hpp @@ -0,0 +1,24 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +namespace mcl::mp { + +/// Converts a list of metavalues to a tuple. +template +struct lower_to_tuple; + +template class LT, class... Es> +struct lower_to_tuple> { + static constexpr auto value = std::make_tuple(static_cast(Es::value)...); +}; + +/// Converts a list of metavalues to a tuple. +template +constexpr auto lower_to_tuple_v = lower_to_tuple::value; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/prepend.hpp b/include/mcl/mp/typelist/prepend.hpp new file mode 100644 index 0000000..df9aedd --- /dev/null +++ b/include/mcl/mp/typelist/prepend.hpp @@ -0,0 +1,25 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +namespace mcl::mp { + +namespace detail { + +template +struct prepend_impl; + +template class LT, class... E1s, class... E2s> +struct prepend_impl, E2s...> { + using type = LT; +}; + +} // namespace detail + +/// Prepend items E to list L +template +using prepend = typename detail::prepend_impl::type; + +} // namespace mcl::mp diff --git a/include/mcl/mp/typelist/tail.hpp b/include/mcl/mp/typelist/tail.hpp new file mode 100644 index 0000000..54f14c1 --- /dev/null +++ b/include/mcl/mp/typelist/tail.hpp @@ -0,0 +1,25 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +namespace mcl::mp { + +namespace detail { + +template +struct tail_impl; + +template class LT, class E1, class... Es> +struct tail_impl> { + using type = LT; +}; + +} // namespace detail + +/// Gets the first type of list L +template +using tail = typename detail::tail_impl::type; + +} // namespace mcl::mp diff --git a/include/mcl/scope_exit.hpp b/include/mcl/scope_exit.hpp index 7a121b8..708c97b 100644 --- a/include/mcl/scope_exit.hpp +++ b/include/mcl/scope_exit.hpp @@ -8,7 +8,7 @@ #include #include -#include "mcl/macro/anonymous_variable.h" +#include "mcl/(.*).hpp" namespace mcl::detail { diff --git a/include/mcl/type_traits/function_info.hpp b/include/mcl/type_traits/function_info.hpp new file mode 100644 index 0000000..2ac804a --- /dev/null +++ b/include/mcl/type_traits/function_info.hpp @@ -0,0 +1,70 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "mcl/mp/typelist/list.hpp" + +namespace mcl { + +template +struct function_info : function_info {}; + +template +struct function_info { + using return_type = R; + using parameter_list = mp::list; + static constexpr std::size_t parameter_count = sizeof...(As); + + using equivalent_function_type = R(As...); + + template + struct parameter { + static_assert(I < parameter_count, "Non-existent parameter"); + using type = std::tuple_element_t>; + }; +}; + +template +struct function_info : function_info {}; + +template +struct function_info : function_info { + using class_type = C; + + using equivalent_function_type_with_class = R(C*, As...); +}; + +template +struct function_info : function_info { + using class_type = C; + + using equivalent_function_type_with_class = R(C*, As...); +}; + +template +constexpr size_t parameter_count_v = function_info::parameter_count; + +template +using parameter_list = typename function_info::parameter_list; + +template +using get_parameter = typename function_info::template parameter::type; + +template +using equivalent_function_type = typename function_info::equivalent_function_type; + +template +using equivalent_function_type_with_class = typename function_info::equivalent_function_type_with_class; + +template +using return_type = typename function_info::return_type; + +template +using class_type = typename function_info::class_type; + +} // namespace mcl diff --git a/include/mcl/type_traits/integer_of_size.hpp b/include/mcl/type_traits/integer_of_size.hpp new file mode 100644 index 0000000..dad2820 --- /dev/null +++ b/include/mcl/type_traits/integer_of_size.hpp @@ -0,0 +1,48 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mp/stdint.hpp" + +namespace mcl { + +namespace detail { + +template +struct integer_of_size_impl {}; + +template<> +struct integer_of_size_impl<8> { + using unsigned_type = u8; + using signed_type = s8; +}; + +template<> +struct integer_of_size_impl<16> { + using unsigned_type = u16; + using signed_type = s16; +}; + +template<> +struct integer_of_size_impl<32> { + using unsigned_type = u32; + using signed_type = s32; +}; + +template<> +struct integer_of_size_impl<64> { + using unsigned_type = u64; + using signed_type = s64; +}; + +} // namespace detail + +template +using unsigned_integer_of_size = typename detail::integer_of_size_impl::unsigned_type; + +template +using signed_integer_of_size = typename detail::integer_of_size_impl::signed_type; + +} // namespace mcl diff --git a/include/mcl/type_traits/is_instance_of_template.hpp b/include/mcl/type_traits/is_instance_of_template.hpp new file mode 100644 index 0000000..8a7fc33 --- /dev/null +++ b/include/mcl/type_traits/is_instance_of_template.hpp @@ -0,0 +1,22 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "mcl/mp/metavalue/value.hpp" + +namespace mcl { + +/// Is type T an instance of template class C? +template class, class> +struct is_instance_of_template : mp::false_type {}; + +template class C, class... As> +struct is_instance_of_template> : mp::true_type {}; + +/// Is type T an instance of template class C? +template class C, class T> +constexpr bool is_instance_of_template_v = is_instance_of_template::value; + +} // namespace mcl diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 01b9164..ed688a6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,17 +5,55 @@ add_library(mcl ../include/mcl/bit/rotate.hpp ../include/mcl/bit/swap.hpp ../include/mcl/bit_cast.hpp + ../include/mcl/bitsizeof.hpp ../include/mcl/concepts/bit_integral.hpp ../include/mcl/concepts/is_any_of.hpp ../include/mcl/concepts/same_as.hpp ../include/mcl/container/intrusive_list.hpp ../include/mcl/hint/assume.hpp + ../include/mcl/iterator/reverse.hpp ../include/mcl/macro/anonymous_variable.hpp ../include/mcl/macro/architecture.hpp ../include/mcl/macro/concatenate_tokens.hpp + ../include/mcl/mp/metafunction/apply.hpp + ../include/mcl/mp/metafunction/bind.hpp + ../include/mcl/mp/metafunction/identity.hpp + ../include/mcl/mp/metafunction/map.hpp + ../include/mcl/mp/metavalue/bit_and.hpp + ../include/mcl/mp/metavalue/bit_not.hpp + ../include/mcl/mp/metavalue/bit_or.hpp + ../include/mcl/mp/metavalue/bit_xor.hpp + ../include/mcl/mp/metavalue/conjunction.hpp + ../include/mcl/mp/metavalue/disjunction.hpp + ../include/mcl/mp/metavalue/lift_value.hpp + ../include/mcl/mp/metavalue/logic_and.hpp + ../include/mcl/mp/metavalue/logic_if.hpp + ../include/mcl/mp/metavalue/logic_not.hpp + ../include/mcl/mp/metavalue/logic_or.hpp + ../include/mcl/mp/metavalue/product.hpp + ../include/mcl/mp/metavalue/sum.hpp + ../include/mcl/mp/metavalue/value.hpp + ../include/mcl/mp/metavalue/value_cast.hpp + ../include/mcl/mp/metavalue/value_equal.hpp + ../include/mcl/mp/misc/argument_count.hpp + ../include/mcl/mp/typelist/append.hpp + ../include/mcl/mp/typelist/cartesian_product.hpp + ../include/mcl/mp/typelist/concat.hpp + ../include/mcl/mp/typelist/contains.hpp + ../include/mcl/mp/typelist/drop.hpp + ../include/mcl/mp/typelist/get.hpp + ../include/mcl/mp/typelist/head.hpp + ../include/mcl/mp/typelist/length.hpp + ../include/mcl/mp/typelist/lift_sequence.hpp + ../include/mcl/mp/typelist/list.hpp + ../include/mcl/mp/typelist/lower_to_tuple.hpp + ../include/mcl/mp/typelist/prepend.hpp + ../include/mcl/mp/typelist/tail.hpp ../include/mcl/scope_exit.hpp ../include/mcl/stdint.hpp - ../include/mcl/stdint.hpp + ../include/mcl/type_traits/function_info.hpp + ../include/mcl/type_traits/integer_of_size.hpp + ../include/mcl/type_traits/is_instance_of_template.hpp assert.cpp ) target_include_directories(mcl PUBLIC ../include/) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 91cb4c6..1b60518 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,8 @@ add_executable(mcl-tests main.cpp + mp/metavalue_tests.cpp + mp/typelist_tests.cpp + type_traits/type_traits_tests.cpp ) target_include_directories(mcl-tests PUBLIC .) target_compile_options(mcl-tests PRIVATE ${STAMINA_CXX_FLAGS}) diff --git a/tests/mp/metavalue_tests.cpp b/tests/mp/metavalue_tests.cpp new file mode 100644 index 0000000..b7d763d --- /dev/null +++ b/tests/mp/metavalue_tests.cpp @@ -0,0 +1,90 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace mcl::mp; + +// bit_and + +static_assert(bit_and, lift_value<1>>::value == 1); + +// bit_not + +static_assert(bit_not>::value == ~0); + +// bit_or + +static_assert(bit_or, lift_value<3>>::value == 3); + +// bit_xor + +static_assert(bit_xor, lift_value<3>>::value == 2); + +// conjunction + +static_assert(std::is_same_v, std::true_type>); +static_assert(std::is_same_v>, lift_value<0>>); +static_assert(std::is_same_v, std::true_type>, std::true_type>); + +// disjunction + +static_assert(std::is_same_v, std::true_type>); +static_assert(std::is_same_v>, lift_value<0>>); +static_assert(std::is_same_v, std::true_type>, lift_value<42>>); + +// lift_value + +static_assert(std::is_same_v, std::integral_constant>); +static_assert(std::is_same_v, std::false_type>); + +// logic_and + +static_assert(std::is_same_v, std::true_type>); +static_assert(std::is_same_v, std::true_type>); +static_assert(std::is_same_v>, std::true_type>); +static_assert(std::is_same_v, std::false_type>); + +// logic_not + +static_assert(std::is_same_v, std::true_type>); + +// logic_or + +static_assert(std::is_same_v, std::false_type>); +static_assert(std::is_same_v, std::true_type>); +static_assert(std::is_same_v>, std::false_type>); +static_assert(std::is_same_v, std::true_type>); + +// product + +static_assert(product, lift_value<2>, lift_value<3>, lift_value<4>>::value == 24); + +// sum + +static_assert(sum, lift_value<2>, lift_value<3>, lift_value<4>>::value == 10); + +// value_cast + +static_assert(std::is_same_v, std::integral_constant>); + +// value_equal + +static_assert(std::is_same_v>, std::true_type>); diff --git a/tests/mp/typelist_tests.cpp b/tests/mp/typelist_tests.cpp new file mode 100644 index 0000000..4f67dc4 --- /dev/null +++ b/tests/mp/typelist_tests.cpp @@ -0,0 +1,104 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace mcl::mp; + +// append + +static_assert(std::is_same_v, double>, list>); +static_assert(std::is_same_v, int, int>, list>); + +// cartesian_product + +static_assert( + std::is_same_v< + cartesian_product, list, list>, + list< + list, + list, + list, + list, + list, + list, + list, + list>>); + +// concat + +static_assert(std::is_same_v, list>, list>); +static_assert(std::is_same_v, list, list>, list>); + +// contains + +static_assert(contains_v, int>); +static_assert(!contains_v, int>); +static_assert(!contains_v, int>); +static_assert(contains_v, int>); + +// drop + +static_assert(std::is_same_v, drop<3, list>>); +static_assert(std::is_same_v, drop<3, list>>); +static_assert(std::is_same_v, drop<3, list>>); +static_assert(std::is_same_v, drop<3, list>>); +static_assert(std::is_same_v, drop<0, list>>); + +// get + +static_assert(std::is_same_v>, int>); +static_assert(std::is_same_v>, double>); + +// head + +static_assert(std::is_same_v>, int>); +static_assert(std::is_same_v>, int>); + +// length + +static_assert(length_v> == 0); +static_assert(length_v> == 1); +static_assert(length_v> == 3); + +// lift_sequence + +static_assert( + std::is_same_v< + lift_sequence>, + list, size_value<1>, size_value<2>>>); + +// lower_to_tuple + +static_assert(lower_to_tuple_v, size_value<1>, size_value<2>>> == std::tuple(0, 1, 2)); +static_assert(lower_to_tuple_v> == std::make_tuple(true, false)); + +// prepend + +static_assert(std::is_same_v, double>, list>); +static_assert(std::is_same_v, double>, list>); +static_assert(std::is_same_v, double, bool>, list>); + +// tail + +static_assert(std::is_same_v>, list>); +static_assert(std::is_same_v>, list<>>); diff --git a/tests/type_traits/type_traits_tests.cpp b/tests/type_traits/type_traits_tests.cpp new file mode 100644 index 0000000..b1a3ed7 --- /dev/null +++ b/tests/type_traits/type_traits_tests.cpp @@ -0,0 +1,39 @@ +// This file is part of the mcl project. +// Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +#include +#include + +#include +#include + +using namespace mcl; + +// function_info + +struct Bar { + int frob(double a) { return a; } +}; + +static_assert(parameter_count_v == 0); +static_assert(parameter_count_v == 3); +static_assert(std::is_same_v, double>); +static_assert(std::is_same_v, void(bool, int, double)>); +static_assert(std::is_same_v, void>); +static_assert(std::is_same_v, int(double)>); +static_assert(std::is_same_v, Bar>); + +// is_instance_of_template + +template +class Foo {}; + +template +class Pair {}; + +static_assert(is_instance_of_template_v>); +static_assert(!is_instance_of_template_v); +static_assert(is_instance_of_template_v>); +static_assert(is_instance_of_template_v>); +static_assert(!is_instance_of_template_v>);