Import mp

This commit is contained in:
Merry 2022-04-19 11:16:33 +01:00
parent 537c4144a1
commit 8b12832172
44 changed files with 1278 additions and 2 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
*build*/
.DS_Store

View File

@ -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<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 mcl::mp

View File

@ -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<template<class...> class F, class... As>
struct bind {
template<class... Rs>
using type = F<As..., Rs...>;
};
} // namespace mcl::mp
#define MCL_MP_BIND(...) ::mcl::mp::bind<__VA_ARGS__>::template type

View File

@ -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<class T>
struct identity_impl {
using type = T;
};
} // namespace detail
/// Identity metafunction
template<class T>
using identity = typename identity_impl<T>::type;
} // namespace mcl::mp

View File

@ -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<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 mcl::mp

View File

@ -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<class... Vs>
using bit_and = lift_value<(Vs::value & ...)>;
/// Bitwise and of metavalues Vs
template<class... Vs>
constexpr auto bit_and_v = (Vs::value & ...);
} // namespace mcl::mp

View File

@ -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<class V>
using bit_not = lift_value<~V::value>;
/// Bitwise not of metavalue V
template<class V>
constexpr auto bit_not_v = ~V::value;
} // namespace mcl::mp

View File

@ -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<class... Vs>
using bit_or = lift_value<(Vs::value | ...)>;
/// Bitwise or of metavalues Vs
template<class... Vs>
constexpr auto bit_or_v = (Vs::value | ...);
} // namespace mcl::mp

View File

@ -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<class... Vs>
using bit_xor = lift_value<(Vs::value ^ ...)>;
/// Bitwise xor of metavalues Vs
template<class... Vs>
constexpr auto bit_xor_v = (Vs::value ^ ...);
} // namespace mcl::mp

View File

@ -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<class...>
struct conjunction_impl;
template<>
struct conjunction_impl<> {
using type = false_type;
};
template<class V>
struct conjunction_impl<V> {
using type = V;
};
template<class V1, class... Vs>
struct conjunction_impl<V1, Vs...> {
using type = logic_if<V1, typename conjunction_impl<Vs...>::type, V1>;
};
} // namespace detail
/// Conjunction of metavalues Vs with short-circuiting and type preservation.
template<class... Vs>
using conjunction = typename detail::conjunction_impl<Vs...>::type;
/// Conjunction of metavalues Vs with short-circuiting and type preservation.
template<class... Vs>
constexpr auto conjunction_v = conjunction<Vs...>::value;
} // namespace mcl::mp

View File

@ -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<class...>
struct disjunction_impl;
template<>
struct disjunction_impl<> {
using type = false_type;
};
template<class V>
struct disjunction_impl<V> {
using type = V;
};
template<class V1, class... Vs>
struct disjunction_impl<V1, Vs...> {
using type = logic_if<V1, V1, typename disjunction_impl<Vs...>::type>;
};
} // namespace detail
/// Disjunction of metavalues Vs with short-circuiting and type preservation.
template<class... Vs>
using disjunction = typename detail::disjunction_impl<Vs...>::type;
/// Disjunction of metavalues Vs with short-circuiting and type preservation.
template<class... Vs>
constexpr auto disjunction_v = disjunction<Vs...>::value;
} // namespace mcl::mp

View File

@ -0,0 +1,15 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#pragma once
#include <type_traits>
namespace mcl::mp {
/// Lifts a value into a type (a metavalue)
template<auto V>
using lift_value = std::integral_constant<decltype(V), V>;
} // namespace mcl::mp

View File

@ -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<class... Vs>
using logic_and = bool_value<(true && ... && Vs::value)>;
/// Logical conjunction of metavalues Vs without short-circuiting or type presevation.
template<class... Vs>
constexpr bool logic_and_v = (true && ... && Vs::value);
} // namespace mcl::mp

View File

@ -0,0 +1,21 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#pragma once
#include <type_traits>
#include "mcl/mp/metavalue/value.hpp"
namespace mcl::mp {
/// Conditionally select between types T and F based on boolean metavalue V
template<class V, class T, class F>
using logic_if = std::conditional_t<bool(V::value), T, F>;
/// Conditionally select between metavalues T and F based on boolean metavalue V
template<class V, class TV, class FV>
constexpr auto logic_if_v = logic_if<V, TV, FV>::value;
} // namespace mcl::mp

View File

@ -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<class V>
using logic_not = bool_value<!bool(V::value)>;
/// Logical negation of metavalue V.
template<class V>
constexpr bool logic_not_v = !bool(V::value);
} // namespace mcl::mp

View File

@ -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<class... Vs>
using logic_or = bool_value<(false || ... || Vs::value)>;
/// Logical disjunction of metavalues Vs without short-circuiting or type presevation.
template<class... Vs>
constexpr bool logic_or_v = (false || ... || Vs::value);
} // namespace mcl::mp

View File

@ -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<class... Vs>
using product = lift_value<(Vs::value * ...)>;
/// Product of metavalues Vs
template<class... Vs>
constexpr auto product_v = (Vs::value * ...);
} // namespace mcl::mp

View File

@ -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<class... Vs>
using sum = lift_value<(Vs::value + ...)>;
/// Sum of metavalues Vs
template<class... Vs>
constexpr auto sum_v = (Vs::value + ...);
} // namespace mcl::mp

View File

@ -0,0 +1,30 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#pragma once
#include <cstddef>
#include <type_traits>
namespace mcl::mp {
/// A metavalue (of type VT and value v).
template<class VT, VT v>
using value = std::integral_constant<VT, v>;
/// A metavalue of type size_t (and value v).
template<size_t v>
using size_value = value<size_t, v>;
/// A metavalue of type bool (and value v). (Aliases to std::bool_constant.)
template<bool v>
using bool_value = value<bool, v>;
/// true metavalue (Aliases to std::true_type).
using true_type = bool_value<true>;
/// false metavalue (Aliases to std::false_type).
using false_type = bool_value<false>;
} // namespace mcl::mp

View File

@ -0,0 +1,15 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#pragma once
#include <type_traits>
namespace mcl::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 mcl::mp

View File

@ -0,0 +1,15 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#pragma once
#include <type_traits>
namespace mcl::mp {
/// Do two metavalues contain the same value?
template<class V1, class V2>
using value_equal = std::bool_constant<V1::value == V2::value>;
} // namespace mcl::mp

View File

@ -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<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 mcl::mp

View File

@ -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... 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 mcl::mp

View File

@ -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<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<MCL_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 mcl::mp

View File

@ -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<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 mcl::mp

View File

@ -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<class L, class T>
struct contains;
template<template<class...> class LT, class... Ts, class T>
struct contains<LT<Ts...>, T>
: bool_value<(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 mcl::mp

View File

@ -0,0 +1,33 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#pragma once
#include <cstddef>
#include <type_traits>
namespace mcl::mp {
namespace detail {
template<size_t N, class L>
struct drop_impl;
template<size_t N, template<class...> class LT>
struct drop_impl<N, LT<>> {
using type = LT<>;
};
template<size_t N, template<class...> class LT, class E1, class... Es>
struct drop_impl<N, LT<E1, Es...>> {
using type = std::conditional_t<N == 0, LT<E1, Es...>, typename drop_impl<N - 1, LT<Es...>>::type>;
};
} // namespace detail
/// Drops the first N elements of list L
template<std::size_t N, class L>
using drop = typename detail::drop_impl<N, L>::type;
} // namespace mcl::mp

View File

@ -0,0 +1,18 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#pragma once
#include <cstddef>
#include <tuple>
#include "mcl/mp/metafunction/apply.hpp"
namespace mcl::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 mcl::mp

View File

@ -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 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 mcl::mp

View File

@ -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<class L>
using length = apply<argument_count, L>;
/// Length of list L
template<class L>
constexpr auto length_v = length<L>::value;
} // namespace mcl::mp

View File

@ -0,0 +1,29 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#pragma once
#include <type_traits>
#include "mcl/mp/typelist/list.hpp"
namespace mcl::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 mcl::mp

View File

@ -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<class... E>
struct list {};
} // namespace mcl::mp

View File

@ -0,0 +1,24 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#pragma once
#include <tuple>
namespace mcl::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 mcl::mp

View File

@ -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... 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 mcl::mp

View File

@ -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 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 mcl::mp

View File

@ -8,7 +8,7 @@
#include <type_traits>
#include <utility>
#include "mcl/macro/anonymous_variable.h"
#include "mcl/(.*).hpp"
namespace mcl::detail {

View File

@ -0,0 +1,70 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#pragma once
#include <cstddef>
#include <tuple>
#include "mcl/mp/typelist/list.hpp"
namespace mcl {
template<class F>
struct function_info : function_info<decltype(&F::operator())> {};
template<class R, class... As>
struct function_info<R(As...)> {
using return_type = R;
using parameter_list = mp::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...)> : function_info<R(As...)> {};
template<class C, class R, class... As>
struct function_info<R (C::*)(As...)> : function_info<R(As...)> {
using class_type = C;
using equivalent_function_type_with_class = R(C*, As...);
};
template<class C, class R, class... As>
struct function_info<R (C::*)(As...) const> : function_info<R(As...)> {
using class_type = C;
using equivalent_function_type_with_class = R(C*, As...);
};
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 equivalent_function_type_with_class = typename function_info<F>::equivalent_function_type_with_class;
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 mcl

View File

@ -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<size_t size>
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<size_t size>
using unsigned_integer_of_size = typename detail::integer_of_size_impl<size>::unsigned_type;
template<size_t size>
using signed_integer_of_size = typename detail::integer_of_size_impl<size>::signed_type;
} // namespace mcl

View File

@ -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<template<class...> class, class>
struct is_instance_of_template : mp::false_type {};
template<template<class...> class C, class... As>
struct is_instance_of_template<C, C<As...>> : mp::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 mcl

View File

@ -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/)

View File

@ -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})

View File

@ -0,0 +1,90 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#include <type_traits>
#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_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>
using namespace mcl::mp;
// bit_and
static_assert(bit_and<lift_value<3>, lift_value<1>>::value == 1);
// bit_not
static_assert(bit_not<lift_value<0>>::value == ~0);
// bit_or
static_assert(bit_or<lift_value<1>, lift_value<3>>::value == 3);
// bit_xor
static_assert(bit_xor<lift_value<1>, lift_value<3>>::value == 2);
// conjunction
static_assert(std::is_same_v<conjunction<std::true_type>, std::true_type>);
static_assert(std::is_same_v<conjunction<std::true_type, lift_value<0>>, lift_value<0>>);
static_assert(std::is_same_v<conjunction<std::true_type, lift_value<42>, std::true_type>, std::true_type>);
// disjunction
static_assert(std::is_same_v<disjunction<std::true_type>, std::true_type>);
static_assert(std::is_same_v<disjunction<std::false_type, lift_value<0>>, lift_value<0>>);
static_assert(std::is_same_v<disjunction<std::false_type, lift_value<42>, std::true_type>, lift_value<42>>);
// 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>);
// logic_and
static_assert(std::is_same_v<logic_and<>, std::true_type>);
static_assert(std::is_same_v<logic_and<std::true_type>, std::true_type>);
static_assert(std::is_same_v<logic_and<lift_value<1>>, std::true_type>);
static_assert(std::is_same_v<logic_and<std::true_type, std::false_type>, std::false_type>);
// logic_not
static_assert(std::is_same_v<logic_not<std::false_type>, std::true_type>);
// logic_or
static_assert(std::is_same_v<logic_or<>, std::false_type>);
static_assert(std::is_same_v<logic_or<std::true_type>, std::true_type>);
static_assert(std::is_same_v<logic_or<lift_value<0>>, std::false_type>);
static_assert(std::is_same_v<logic_or<std::true_type, std::false_type>, std::true_type>);
// product
static_assert(product<lift_value<1>, lift_value<2>, lift_value<3>, lift_value<4>>::value == 24);
// sum
static_assert(sum<lift_value<1>, lift_value<2>, lift_value<3>, lift_value<4>>::value == 10);
// 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>);

104
tests/mp/typelist_tests.cpp Normal file
View File

@ -0,0 +1,104 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>
#include <mcl/mp/metavalue/value.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>
using namespace mcl::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>);
// drop
static_assert(std::is_same_v<list<>, drop<3, list<int, int>>>);
static_assert(std::is_same_v<list<>, drop<3, list<int, int, int>>>);
static_assert(std::is_same_v<list<int>, drop<3, list<int, int, int, int>>>);
static_assert(std::is_same_v<list<double>, drop<3, list<int, int, int, double>>>);
static_assert(std::is_same_v<list<int, double, bool>, drop<0, list<int, double, bool>>>);
// 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<size_value<0>, size_value<1>, size_value<2>>>);
// lower_to_tuple
static_assert(lower_to_tuple_v<list<size_value<0>, size_value<1>, size_value<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<>>);

View File

@ -0,0 +1,39 @@
// This file is part of the mcl project.
// Copyright (c) 2022 merryhime
// SPDX-License-Identifier: MIT
#include <tuple>
#include <type_traits>
#include <mcl/type_traits/function_info.hpp>
#include <mcl/type_traits/is_instance_of_template.hpp>
using namespace mcl;
// 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>>);