Squashed 'externals/mp/' content from commit 29cb5588d
git-subtree-dir: externals/mp git-subtree-split: 29cb5588da3a18ed571a0e41622900a01b9f01eb
This commit is contained in:
commit
7b0c47d3f0
30 changed files with 971 additions and 0 deletions
22
.travis.yml
Normal file
22
.travis.yml
Normal file
|
@ -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
|
12
LICENSE-0BSD
Normal file
12
LICENSE-0BSD
Normal file
|
@ -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.
|
111
README.md
Normal file
111
README.md
Normal file
|
@ -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).
|
26
include/mp/metafunction/apply.h
Normal file
26
include/mp/metafunction/apply.h
Normal file
|
@ -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<template<class...> class F, class L>
|
||||
struct apply_impl;
|
||||
|
||||
template<template<class...> class F, template<class...> class LT, class... Es>
|
||||
struct apply_impl<F, LT<Es...>> {
|
||||
using type = F<Es...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Invokes metafunction F where the arguments are all the members of list L
|
||||
template<template<class...> class F, class L>
|
||||
using apply = typename detail::apply_impl<F, L>::type;
|
||||
|
||||
} // namespace mp
|
19
include/mp/metafunction/bind.h
Normal file
19
include/mp/metafunction/bind.h
Normal file
|
@ -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<template<class...> class F, class... As>
|
||||
struct bind {
|
||||
template<class... Rs>
|
||||
using type = F<As..., Rs...>;
|
||||
};
|
||||
|
||||
} // namespace mp
|
||||
|
||||
#define MM_MP_BIND(...) ::mp::bind<__VA_ARGS__>::template type
|
23
include/mp/metafunction/identity.h
Normal file
23
include/mp/metafunction/identity.h
Normal file
|
@ -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<class T>
|
||||
struct identity_impl {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Identity metafunction
|
||||
template<class T>
|
||||
using identity = typename identity_impl<T>::type;
|
||||
|
||||
} // namespace mp
|
26
include/mp/metafunction/map.h
Normal file
26
include/mp/metafunction/map.h
Normal file
|
@ -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<template<class...> class F, class L>
|
||||
struct map_impl;
|
||||
|
||||
template<template<class...> class F, template<class...> class LT, class... Es>
|
||||
struct map_impl<F, LT<Es...>> {
|
||||
using type = LT<F<Es>...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Applies each element of list L to metafunction F
|
||||
template<template<class...> class F, class L>
|
||||
using map = typename detail::map_impl<F, L>::type;
|
||||
|
||||
} // namespace mp
|
16
include/mp/metavalue/lift_value.h
Normal file
16
include/mp/metavalue/lift_value.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace mp {
|
||||
|
||||
/// Lifts a value into a type (a metavalue)
|
||||
template<auto V>
|
||||
using lift_value = std::integral_constant<decltype(V), V>;
|
||||
|
||||
} // namespace mp
|
16
include/mp/metavalue/value_cast.h
Normal file
16
include/mp/metavalue/value_cast.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace mp {
|
||||
|
||||
/// Casts a metavalue from one type to another
|
||||
template<class T, class V>
|
||||
using value_cast = std::integral_constant<T, static_cast<T>(V::value)>;
|
||||
|
||||
} // namespace mp
|
16
include/mp/metavalue/value_equal.h
Normal file
16
include/mp/metavalue/value_equal.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2020 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace mp {
|
||||
|
||||
/// Do two metavalues contain the same value?
|
||||
template<class V1, class V2>
|
||||
using value_equal = std::bool_constant<V1::value == V2::value>;
|
||||
|
||||
} // namespace mp
|
20
include/mp/misc/argument_count.h
Normal file
20
include/mp/misc/argument_count.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mp/metavalue/lift_value.h>
|
||||
|
||||
namespace mp {
|
||||
|
||||
/// Metafunction that returns the number of arguments it has
|
||||
template<typename... Ts>
|
||||
using argument_count = lift_value<sizeof...(Ts)>;
|
||||
|
||||
/// Metafunction that returns the number of arguments it has
|
||||
template<typename... Ts>
|
||||
constexpr auto argument_count_v = sizeof...(Ts);
|
||||
|
||||
} // namespace mp
|
64
include/mp/traits/function_info.h
Normal file
64
include/mp/traits/function_info.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
|
||||
#include <mp/typelist/list.h>
|
||||
|
||||
namespace mp {
|
||||
|
||||
template<class F>
|
||||
struct function_info : public function_info<decltype(&F::operator())> {};
|
||||
|
||||
template<class R, class... As>
|
||||
struct function_info<R(As...)> {
|
||||
using return_type = R;
|
||||
using parameter_list = list<As...>;
|
||||
static constexpr std::size_t parameter_count = sizeof...(As);
|
||||
|
||||
using equivalent_function_type = R(As...);
|
||||
|
||||
template<std::size_t I>
|
||||
struct parameter {
|
||||
static_assert(I < parameter_count, "Non-existent parameter");
|
||||
using type = std::tuple_element_t<I, std::tuple<As...>>;
|
||||
};
|
||||
};
|
||||
|
||||
template<class R, class... As>
|
||||
struct function_info<R(*)(As...)> : public function_info<R(As...)> {};
|
||||
|
||||
template<class C, class R, class... As>
|
||||
struct function_info<R(C::*)(As...)> : public function_info<R(As...)> {
|
||||
using class_type = C;
|
||||
};
|
||||
|
||||
template<class C, class R, class... As>
|
||||
struct function_info<R(C::*)(As...) const> : public function_info<R(As...)> {
|
||||
using class_type = C;
|
||||
};
|
||||
|
||||
template<class F>
|
||||
constexpr size_t parameter_count_v = function_info<F>::parameter_count;
|
||||
|
||||
template<class F>
|
||||
using parameter_list = typename function_info<F>::parameter_list;
|
||||
|
||||
template<class F, std::size_t I>
|
||||
using get_parameter = typename function_info<F>::template parameter<I>::type;
|
||||
|
||||
template<class F>
|
||||
using equivalent_function_type = typename function_info<F>::equivalent_function_type;
|
||||
|
||||
template<class F>
|
||||
using return_type = typename function_info<F>::return_type;
|
||||
|
||||
template<class F>
|
||||
using class_type = typename function_info<F>::class_type;
|
||||
|
||||
} // namespace mp
|
50
include/mp/traits/integer_of_size.h
Normal file
50
include/mp/traits/integer_of_size.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<std::size_t size>
|
||||
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<std::size_t size>
|
||||
using unsigned_integer_of_size = typename detail::integer_of_size_impl<size>::unsigned_type;
|
||||
|
||||
template<std::size_t size>
|
||||
using signed_integer_of_size = typename detail::integer_of_size_impl<size>::signed_type;
|
||||
|
||||
} // namespace mp
|
23
include/mp/traits/is_instance_of_template.h
Normal file
23
include/mp/traits/is_instance_of_template.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2020 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace mp {
|
||||
|
||||
/// Is type T an instance of template class C?
|
||||
template <template <class...> class, class>
|
||||
struct is_instance_of_template : public std::false_type {};
|
||||
|
||||
template <template <class...> class C, class... As>
|
||||
struct is_instance_of_template<C, C<As...>> : public std::true_type {};
|
||||
|
||||
/// Is type T an instance of template class C?
|
||||
template<template <class...> class C, class T>
|
||||
constexpr bool is_instance_of_template_v = is_instance_of_template<C, T>::value;
|
||||
|
||||
} // namespace mp
|
26
include/mp/typelist/append.h
Normal file
26
include/mp/typelist/append.h
Normal file
|
@ -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... L>
|
||||
struct append_impl;
|
||||
|
||||
template<template<class...> class LT, class... E1s, class... E2s>
|
||||
struct append_impl<LT<E1s...>, E2s...> {
|
||||
using type = LT<E1s..., E2s...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Append items E to list L
|
||||
template<class L, class... Es>
|
||||
using append = typename detail::append_impl<L, Es...>::type;
|
||||
|
||||
} // namespace mp
|
50
include/mp/typelist/cartesian_product.h
Normal file
50
include/mp/typelist/cartesian_product.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mp/metafunction/bind.h>
|
||||
#include <mp/metafunction/map.h>
|
||||
#include <mp/typelist/append.h>
|
||||
#include <mp/typelist/concat.h>
|
||||
#include <mp/typelist/list.h>
|
||||
|
||||
namespace mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class... Ls>
|
||||
struct cartesian_product_impl;
|
||||
|
||||
template<class RL>
|
||||
struct cartesian_product_impl<RL> {
|
||||
using type = RL;
|
||||
};
|
||||
|
||||
template<template<class...> class LT, class... REs, class... E2s>
|
||||
struct cartesian_product_impl<LT<REs...>, LT<E2s...>> {
|
||||
using type = concat<
|
||||
map<MM_MP_BIND(append, REs), list<E2s...>>...
|
||||
>;
|
||||
};
|
||||
|
||||
template<class RL, class L2, class L3, class... Ls>
|
||||
struct cartesian_product_impl<RL, L2, L3, Ls...> {
|
||||
using type = typename cartesian_product_impl<
|
||||
typename cartesian_product_impl<RL, L2>::type,
|
||||
L3,
|
||||
Ls...
|
||||
>::type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Produces the cartesian product of a set of lists
|
||||
/// For example:
|
||||
/// cartesian_product<list<A, B>, list<D, E>> == list<list<A, D>, list<A, E>, list<B, D>, list<B, E>
|
||||
template<typename L1, typename... Ls>
|
||||
using cartesian_product = typename detail::cartesian_product_impl<map<list, L1>, Ls...>::type;
|
||||
|
||||
} // namespace mp
|
56
include/mp/typelist/concat.h
Normal file
56
include/mp/typelist/concat.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mp/typelist/list.h>
|
||||
|
||||
namespace mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class... Ls>
|
||||
struct concat_impl;
|
||||
|
||||
template<>
|
||||
struct concat_impl<> {
|
||||
using type = list<>;
|
||||
};
|
||||
|
||||
template<class L>
|
||||
struct concat_impl<L> {
|
||||
using type = L;
|
||||
};
|
||||
|
||||
template<template<class...> class LT, class... E1s, class... E2s, class... Ls>
|
||||
struct concat_impl<LT<E1s...>, LT<E2s...>, Ls...> {
|
||||
using type = typename concat_impl<LT<E1s..., E2s...>, Ls...>::type;
|
||||
};
|
||||
|
||||
template<template<class...> 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<E1s...>, LT<E2s...>, LT<E3s...>, LT<E4s...>, LT<E5s...>, LT<E6s...>, LT<E7s...>, LT<E8s...>,
|
||||
LT<E9s...>, LT<E10s...>, LT<E11s...>, LT<E12s...>, LT<E13s...>, LT<E14s...>, LT<E15s...>, LT<E16s...>,
|
||||
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<class... Ls>
|
||||
using concat = typename detail::concat_impl<Ls...>::type;
|
||||
|
||||
} // namespace mp
|
25
include/mp/typelist/contains.h
Normal file
25
include/mp/typelist/contains.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* Ehis file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace mp {
|
||||
|
||||
/// Does list L contain an element which is same as type T?
|
||||
template<class L, class T>
|
||||
struct contains;
|
||||
|
||||
template<template<class...> class LT, class... Ts, class T>
|
||||
struct contains<LT<Ts...>, T>
|
||||
: public std::bool_constant<(false || ... || std::is_same_v<Ts, T>)>
|
||||
{};
|
||||
|
||||
/// Does list L contain an element which is same as type T?
|
||||
template<class L, class T>
|
||||
constexpr bool contains_v = contains<L, T>::value;
|
||||
|
||||
} // namespace mp
|
19
include/mp/typelist/get.h
Normal file
19
include/mp/typelist/get.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
|
||||
#include <mp/metafunction/apply.h>
|
||||
|
||||
namespace mp {
|
||||
|
||||
/// Get element I from list L
|
||||
template<std::size_t I, class L>
|
||||
using get = std::tuple_element_t<I, apply<std::tuple, L>>;
|
||||
|
||||
} // namespace mp
|
26
include/mp/typelist/head.h
Normal file
26
include/mp/typelist/head.h
Normal file
|
@ -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 L>
|
||||
struct head_impl;
|
||||
|
||||
template<template<class...> class LT, class E1, class... Es>
|
||||
struct head_impl<LT<E1, Es...>> {
|
||||
using type = E1;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Gets the tail/cdr/all-but-the-first-element of list L
|
||||
template<class L>
|
||||
using head = typename detail::head_impl<L>::type;
|
||||
|
||||
} // namespace mp
|
21
include/mp/typelist/length.h
Normal file
21
include/mp/typelist/length.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mp/metafunction/apply.h>
|
||||
#include <mp/misc/argument_count.h>
|
||||
|
||||
namespace mp {
|
||||
|
||||
/// Length of list L
|
||||
template<class L>
|
||||
using length = apply<argument_count, L>;
|
||||
|
||||
/// Length of list L
|
||||
template<class L>
|
||||
constexpr auto length_v = length<L>::value;
|
||||
|
||||
} // namespace mp
|
30
include/mp/typelist/lift_sequence.h
Normal file
30
include/mp/typelist/lift_sequence.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <mp/typelist/list.h>
|
||||
|
||||
namespace mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class VL>
|
||||
struct lift_sequence_impl;
|
||||
|
||||
template<class T, template <class, T...> class VLT, T... values>
|
||||
struct lift_sequence_impl<VLT<T, values...>> {
|
||||
using type = list<std::integral_constant<T, values>...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Lifts values in value list VL to create a type list.
|
||||
template<class VL>
|
||||
using lift_sequence = typename detail::lift_sequence_impl<VL>::type;
|
||||
|
||||
} // namespace mp
|
14
include/mp/typelist/list.h
Normal file
14
include/mp/typelist/list.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace mp {
|
||||
|
||||
/// Contains a list of types
|
||||
template<class... E>
|
||||
struct list {};
|
||||
|
||||
} // namespace mp
|
25
include/mp/typelist/lower_to_tuple.h
Normal file
25
include/mp/typelist/lower_to_tuple.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2017 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace mp {
|
||||
|
||||
/// Converts a list of metavalues to a tuple.
|
||||
template<class L>
|
||||
struct lower_to_tuple;
|
||||
|
||||
template<template<class...> class LT, class... Es>
|
||||
struct lower_to_tuple<LT<Es...>> {
|
||||
static constexpr auto value = std::make_tuple(static_cast<typename Es::value_type>(Es::value)...);
|
||||
};
|
||||
|
||||
/// Converts a list of metavalues to a tuple.
|
||||
template<class L>
|
||||
constexpr auto lower_to_tuple_v = lower_to_tuple<L>::value;
|
||||
|
||||
} // namespace mp
|
26
include/mp/typelist/prepend.h
Normal file
26
include/mp/typelist/prepend.h
Normal file
|
@ -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... L>
|
||||
struct prepend_impl;
|
||||
|
||||
template<template<class...> class LT, class... E1s, class... E2s>
|
||||
struct prepend_impl<LT<E1s...>, E2s...> {
|
||||
using type = LT<E2s..., E1s...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Prepend items E to list L
|
||||
template<class L, class... Es>
|
||||
using prepend = typename detail::prepend_impl<L, Es...>::type;
|
||||
|
||||
} // namespace mp
|
26
include/mp/typelist/tail.h
Normal file
26
include/mp/typelist/tail.h
Normal file
|
@ -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 L>
|
||||
struct tail_impl;
|
||||
|
||||
template<template<class...> class LT, class E1, class... Es>
|
||||
struct tail_impl<LT<E1, Es...>> {
|
||||
using type = LT<Es...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Gets the first type of list L
|
||||
template<class L>
|
||||
using tail = typename detail::tail_impl<L>::type;
|
||||
|
||||
} // namespace mp
|
12
tests/all_tests.cpp
Normal file
12
tests/all_tests.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2020 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include "metavalue_tests.h"
|
||||
#include "traits_tests.h"
|
||||
#include "typelist_tests.h"
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
27
tests/metavalue_tests.h
Normal file
27
tests/metavalue_tests.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2020 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <mp/metavalue/lift_value.h>
|
||||
#include <mp/metavalue/value_cast.h>
|
||||
#include <mp/metavalue/value_equal.h>
|
||||
|
||||
using namespace mp;
|
||||
|
||||
// lift_value
|
||||
|
||||
static_assert(std::is_same_v<lift_value<3>, std::integral_constant<int, 3>>);
|
||||
static_assert(std::is_same_v<lift_value<false>, std::false_type>);
|
||||
|
||||
// value_cast
|
||||
|
||||
static_assert(std::is_same_v<value_cast<int, std::true_type>, std::integral_constant<int, 1>>);
|
||||
|
||||
// value_equal
|
||||
|
||||
static_assert(std::is_same_v<value_equal<std::true_type, std::integral_constant<int, 1>>, std::true_type>);
|
42
tests/traits_tests.h
Normal file
42
tests/traits_tests.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2020 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#include <mp/traits/function_info.h>
|
||||
#include <mp/traits/is_instance_of_template.h>
|
||||
|
||||
using namespace mp;
|
||||
|
||||
// function_info
|
||||
|
||||
struct Bar {
|
||||
int frob(double a) { return a; }
|
||||
};
|
||||
|
||||
static_assert(parameter_count_v<void()> == 0);
|
||||
static_assert(parameter_count_v<void(int, int, int)> == 3);
|
||||
static_assert(std::is_same_v<get_parameter<void(*)(bool, int, double), 2>, double>);
|
||||
static_assert(std::is_same_v<equivalent_function_type<void(*)(bool, int, double)>, void(bool, int, double)>);
|
||||
static_assert(std::is_same_v<return_type<void(*)(bool, int, double)>, void>);
|
||||
static_assert(std::is_same_v<equivalent_function_type<decltype(&Bar::frob)>, int(double)>);
|
||||
static_assert(std::is_same_v<class_type<decltype(&Bar::frob)>, Bar>);
|
||||
|
||||
// is_instance_of_template
|
||||
|
||||
template<class, class...>
|
||||
class Foo {};
|
||||
|
||||
template<class, class>
|
||||
class Pair {};
|
||||
|
||||
static_assert(is_instance_of_template_v<std::tuple, std::tuple<int, bool>>);
|
||||
static_assert(!is_instance_of_template_v<std::tuple, bool>);
|
||||
static_assert(is_instance_of_template_v<Foo, Foo<bool>>);
|
||||
static_assert(is_instance_of_template_v<Pair, Pair<bool, int>>);
|
||||
static_assert(!is_instance_of_template_v<Pair, Foo<bool, int>>);
|
102
tests/typelist_tests.h
Normal file
102
tests/typelist_tests.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/* This file is part of the mp project.
|
||||
* Copyright (c) 2020 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <mp/typelist/append.h>
|
||||
#include <mp/typelist/cartesian_product.h>
|
||||
#include <mp/typelist/concat.h>
|
||||
#include <mp/typelist/contains.h>
|
||||
#include <mp/typelist/get.h>
|
||||
#include <mp/typelist/head.h>
|
||||
#include <mp/typelist/length.h>
|
||||
#include <mp/typelist/lift_sequence.h>
|
||||
#include <mp/typelist/list.h>
|
||||
#include <mp/typelist/lower_to_tuple.h>
|
||||
#include <mp/typelist/prepend.h>
|
||||
#include <mp/typelist/tail.h>
|
||||
|
||||
using namespace mp;
|
||||
|
||||
// append
|
||||
|
||||
static_assert(std::is_same_v<append<list<int, bool>, double>, list<int, bool, double>>);
|
||||
static_assert(std::is_same_v<append<list<>, int, int>, list<int, int>>);
|
||||
|
||||
// cartesian_product
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
cartesian_product<list<int, bool>, list<double, float>, list<char, unsigned>>,
|
||||
list<
|
||||
list<int, double, char>,
|
||||
list<int, double, unsigned>,
|
||||
list<int, float, char>,
|
||||
list<int, float, unsigned>,
|
||||
list<bool, double, char>,
|
||||
list<bool, double, unsigned>,
|
||||
list<bool, float, char>,
|
||||
list<bool, float, unsigned>
|
||||
>
|
||||
>
|
||||
);
|
||||
|
||||
// concat
|
||||
|
||||
static_assert(std::is_same_v<concat<list<int, bool>, list<double>>, list<int, bool, double>>);
|
||||
static_assert(std::is_same_v<concat<list<>, list<int>, list<int>>, list<int, int>>);
|
||||
|
||||
// contains
|
||||
|
||||
static_assert(contains_v<list<int>, int>);
|
||||
static_assert(!contains_v<list<>, int>);
|
||||
static_assert(!contains_v<list<double>, int>);
|
||||
static_assert(contains_v<list<double, int>, int>);
|
||||
|
||||
// get
|
||||
|
||||
static_assert(std::is_same_v<get<0, list<int, double>>, int>);
|
||||
static_assert(std::is_same_v<get<1, list<int, double>>, double>);
|
||||
|
||||
// head
|
||||
|
||||
static_assert(std::is_same_v<head<list<int, double>>, int>);
|
||||
static_assert(std::is_same_v<head<list<int>>, int>);
|
||||
|
||||
// length
|
||||
|
||||
static_assert(length_v<list<>> == 0);
|
||||
static_assert(length_v<list<int>> == 1);
|
||||
static_assert(length_v<list<int, int, int>> == 3);
|
||||
|
||||
// lift_sequence
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
lift_sequence<std::make_index_sequence<3>>,
|
||||
list<std::integral_constant<std::size_t, 0>, std::integral_constant<std::size_t, 1>, std::integral_constant<std::size_t, 2>>
|
||||
>
|
||||
);
|
||||
|
||||
// lower_to_tuple
|
||||
|
||||
static_assert(lower_to_tuple_v<list<std::integral_constant<std::size_t, 0>, std::integral_constant<std::size_t, 1>, std::integral_constant<std::size_t, 2>>> == std::tuple<std::size_t, std::size_t, std::size_t>(0, 1, 2));
|
||||
static_assert(lower_to_tuple_v<list<std::true_type, std::false_type>> == std::make_tuple(true, false));
|
||||
|
||||
// prepend
|
||||
|
||||
static_assert(std::is_same_v<prepend<list<int, int>, double>, list<double, int, int>>);
|
||||
static_assert(std::is_same_v<prepend<list<>, double>, list<double>>);
|
||||
static_assert(std::is_same_v<prepend<list<int>, double, bool>, list<double, bool, int>>);
|
||||
|
||||
// tail
|
||||
|
||||
static_assert(std::is_same_v<tail<list<int, double>>, list<double>>);
|
||||
static_assert(std::is_same_v<tail<list<int>>, list<>>);
|
Loading…
Reference in a new issue