commit 7b0c47d3f0c20eeeceb0324771eb86ab80b0bd86 Author: MerryMage Date: Wed Apr 22 21:05:25 2020 +0100 Squashed 'externals/mp/' content from commit 29cb5588d git-subtree-dir: externals/mp git-subtree-split: 29cb5588da3a18ed571a0e41622900a01b9f01eb diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..e864bf47 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +language: cpp +os: linux + +matrix: + - compiler: clang + env: CXX=clang + dist: bionic + - compiler: g++-7 + env: CXX=g++-7 + dist: bionic + - compiler: g++-8 + env: CXX=g++-8 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-8 + +script: + - $CXX --version + - $CXX -I./include -std=c++17 -Wall -Wextra -Wcast-qual -pedantic -pedantic-errors -Werror tests/all_tests.cpp diff --git a/LICENSE-0BSD b/LICENSE-0BSD new file mode 100644 index 00000000..6de06bcf --- /dev/null +++ b/LICENSE-0BSD @@ -0,0 +1,12 @@ +Copyright (C) 2017 MerryMage + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..f4c0e5de --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +mp +=== + +A small, 0BSD-licensed metaprogramming library for C++17. + +This is intended to be a lightweight and easy to understand implementation of a subset of useful metaprogramming utilities. + +Usage +----- + +Just add the `include` directory to your include path. That's it. + +`typelist` +---------- + +A `mp::list` is a list of types. This set of headers provide metafunctions for manipulating lists of types. + +### Constructor + +* `mp::list`: Constructs a list. +* `mp::lift_sequence`: Lifts a value sequence into a list. Intended for use on `std::integral_sequence`. + +### Element access + +* `mp::get`: Gets a numbered element of a list. +* `mp::head`: Gets the first element of a list. +* `mp::tail`: Gets all-but-the-first-element as a list. + +### Properties + +* `mp::length`: Gets the length of a list. +* `mp::contains`: Determines if this list contains a specified element. + +### Modifiers + +* `mp::append`: Constructs a list with the provided elements appended to it. +* `mp::prepend`: Constructs a list with the provided elements prepended to it. + +### Operations + +* `mp::concat`: Concantenates multiple lists together. +* `mp::cartesian_product`: Construct a list containing the [cartesian product](https://en.wikipedia.org/wiki/Cartesian_product) of the provided lists. + +### Conversions + +* `mp::lower_to_tuple`: This operation only works on a list solely containing metavalues. Results in a `std::tuple` with equivalent values. + + +`metavalue` +----------- + +A metavalue is a type of template `std::integral_constant`. + +### Constants + +* [`std::true_type`](https://en.cppreference.com/w/cpp/types/integral_constant) +* [`std::false_type`](https://en.cppreference.com/w/cpp/types/integral_constant) + +### Constructor + +* [`std::integral_constant`](https://en.cppreference.com/w/cpp/types/integral_constant) +* [`std::bool_constant`](https://en.cppreference.com/w/cpp/types/integral_constant) +* `mp::lift_value`: Lifts a value to become a metavalue + +### Conversions + +* `mp::value_cast` + +### Operations + +* `mp::value_equal`: Compares value equality, ignores type. Use `std::is_same` for strict comparison. +* [`std::negation`](https://en.cppreference.com/w/cpp/types/negation) +* [`std::conjunction`](https://en.cppreference.com/w/cpp/types/conjunction) +* [`std::disjunction`](https://en.cppreference.com/w/cpp/types/disjunction) + +`metafunction` +-------------- + +* `std::void_t`: Always returns `void`. +* `mp::identity`: Identity metafunction. Can be used to establish a non-deduced context. See also C++20 `std::type_identity`. +* `mp::apply`: Invoke a provided metafunction with arguments specified in a list. +* `mp::map`: Apply a provided metafunction to each element of a list. +* `mp::bind`: Curry a metafunction. A macro `MM_MP_BIND` is provided to make this a little prettier. + +`traits` +-------- + +Type traits not in the standard library. + +### `function_info` + +* `mp::parameter_count_v`: Number of parameters a function has +* `mp::parameter_list`: Get a typelist of the parameter types +* `mp::get_parameter`: Get the type of a parameter by index +* `mp::equivalent_function_type`: Get an equivalent function type (for MFPs this does not include the class) +* `mp::return_type`: Return type of the function +* `mp::class_type`: Only valid for member function pointer types. Gets the class the member function is associated with. + +### `integer_of_size` + +* `mp::signed_integer_of_size`: Gets a signed integer of the specified bit-size (if it exists) +* `mp::unsigned_integer_of_size`: Gets an unsigned integer of the specified bit-size (if it exists) + +### Misc + +* `mp::is_instance_of_template`: Checks if a type is an instance of a template class. + +License +------- + +Please see [LICENSE-0BSD](LICENSE-0BSD). diff --git a/include/mp/metafunction/apply.h b/include/mp/metafunction/apply.h new file mode 100644 index 00000000..6ccf1a5f --- /dev/null +++ b/include/mp/metafunction/apply.h @@ -0,0 +1,26 @@ +/* Ehis file is part of the mp project. + * Copyright (c) 2017 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +namespace 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 mp diff --git a/include/mp/metafunction/bind.h b/include/mp/metafunction/bind.h new file mode 100644 index 00000000..ec3b5163 --- /dev/null +++ b/include/mp/metafunction/bind.h @@ -0,0 +1,19 @@ +/* This file is part of the mp project. + * Copyright (c) 2017 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +namespace 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 mp + +#define MM_MP_BIND(...) ::mp::bind<__VA_ARGS__>::template type diff --git a/include/mp/metafunction/identity.h b/include/mp/metafunction/identity.h new file mode 100644 index 00000000..661af9a6 --- /dev/null +++ b/include/mp/metafunction/identity.h @@ -0,0 +1,23 @@ +/* This file is part of the mp project. + * Copyright (c) 2017 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +namespace mp { + +namespace detail { + +template +struct identity_impl { + using type = T; +}; + +} // namespace detail + +/// Identity metafunction +template +using identity = typename identity_impl::type; + +} // namespace mp diff --git a/include/mp/metafunction/map.h b/include/mp/metafunction/map.h new file mode 100644 index 00000000..28aa1f5b --- /dev/null +++ b/include/mp/metafunction/map.h @@ -0,0 +1,26 @@ +/* This file is part of the mp project. + * Copyright (c) 2017 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +namespace 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 mp diff --git a/include/mp/metavalue/lift_value.h b/include/mp/metavalue/lift_value.h new file mode 100644 index 00000000..74dd3347 --- /dev/null +++ b/include/mp/metavalue/lift_value.h @@ -0,0 +1,16 @@ +/* This file is part of the mp project. + * Copyright (c) 2017 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include + +namespace mp { + +/// Lifts a value into a type (a metavalue) +template +using lift_value = std::integral_constant; + +} // namespace mp diff --git a/include/mp/metavalue/value_cast.h b/include/mp/metavalue/value_cast.h new file mode 100644 index 00000000..a05e45ee --- /dev/null +++ b/include/mp/metavalue/value_cast.h @@ -0,0 +1,16 @@ +/* This file is part of the mp project. + * Copyright (c) 2017 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include + +namespace mp { + +/// Casts a metavalue from one type to another +template +using value_cast = std::integral_constant(V::value)>; + +} // namespace mp diff --git a/include/mp/metavalue/value_equal.h b/include/mp/metavalue/value_equal.h new file mode 100644 index 00000000..dde387f9 --- /dev/null +++ b/include/mp/metavalue/value_equal.h @@ -0,0 +1,16 @@ +/* This file is part of the mp project. + * Copyright (c) 2020 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include + +namespace mp { + +/// Do two metavalues contain the same value? +template +using value_equal = std::bool_constant; + +} // namespace mp diff --git a/include/mp/misc/argument_count.h b/include/mp/misc/argument_count.h new file mode 100644 index 00000000..f334b69c --- /dev/null +++ b/include/mp/misc/argument_count.h @@ -0,0 +1,20 @@ +/* This file is part of the mp project. + * Copyright (c) 2017 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include + +namespace 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 mp diff --git a/include/mp/traits/function_info.h b/include/mp/traits/function_info.h new file mode 100644 index 00000000..a2344cfe --- /dev/null +++ b/include/mp/traits/function_info.h @@ -0,0 +1,64 @@ +/* This file is part of the mp project. + * Copyright (c) 2017 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include +#include + +#include + +namespace mp { + +template +struct function_info : public function_info {}; + +template +struct function_info { + using return_type = R; + using parameter_list = 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 : public function_info {}; + +template +struct function_info : public function_info { + using class_type = C; +}; + +template +struct function_info : public function_info { + using class_type = C; +}; + +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 return_type = typename function_info::return_type; + +template +using class_type = typename function_info::class_type; + +} // namespace mp diff --git a/include/mp/traits/integer_of_size.h b/include/mp/traits/integer_of_size.h new file mode 100644 index 00000000..651b1636 --- /dev/null +++ b/include/mp/traits/integer_of_size.h @@ -0,0 +1,50 @@ +/* This file is part of the mp project. + * Copyright (c) 2018 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include +#include + +namespace mp { + +namespace detail { + +template +struct integer_of_size_impl{}; + +template<> +struct integer_of_size_impl<8> { + using unsigned_type = std::uint8_t; + using signed_type = std::int8_t; +}; + +template<> +struct integer_of_size_impl<16> { + using unsigned_type = std::uint16_t; + using signed_type = std::int16_t; +}; + +template<> +struct integer_of_size_impl<32> { + using unsigned_type = std::uint32_t; + using signed_type = std::int32_t; +}; + +template<> +struct integer_of_size_impl<64> { + using unsigned_type = std::uint64_t; + using signed_type = std::int64_t; +}; + +} // 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 mp diff --git a/include/mp/traits/is_instance_of_template.h b/include/mp/traits/is_instance_of_template.h new file mode 100644 index 00000000..3299e8c3 --- /dev/null +++ b/include/mp/traits/is_instance_of_template.h @@ -0,0 +1,23 @@ +/* This file is part of the mp project. + * Copyright (c) 2020 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include + +namespace mp { + +/// Is type T an instance of template class C? +template