Squashed 'externals/mp/' changes from 29cb5588d..649fde1e8

649fde1e8 typelist: Add drop
5efe868da travis: Drop GCC 7 from CI
c3f890f17 Update to use new metavalue types
c4dd1c9b9 metavalue: Add some common operations
7da45c71b Remove unnecessary public keyword for struct inheritance
287d8e7ec Correct typos in file headers

git-subtree-dir: externals/mp
git-subtree-split: 649fde1e814f9ce5b04d7ddeb940244d9f63cb2f
This commit is contained in:
MerryMage 2020-04-22 21:06:56 +01:00
parent 7b0c47d3f0
commit 1925d4dcc6
22 changed files with 460 additions and 24 deletions

View file

@ -5,9 +5,6 @@ matrix:
- compiler: clang - compiler: clang
env: CXX=clang env: CXX=clang
dist: bionic dist: bionic
- compiler: g++-7
env: CXX=g++-7
dist: bionic
- compiler: g++-8 - compiler: g++-8
env: CXX=g++-8 env: CXX=g++-8
addons: addons:

View file

@ -53,14 +53,15 @@ A metavalue is a type of template `std::integral_constant`.
### Constants ### Constants
* [`std::true_type`](https://en.cppreference.com/w/cpp/types/integral_constant) * mp::true_type: Aliases to [`std::true_type`](https://en.cppreference.com/w/cpp/types/integral_constant)
* [`std::false_type`](https://en.cppreference.com/w/cpp/types/integral_constant) * mp::false_type: Aliases to [`mp::false_type`](https://en.cppreference.com/w/cpp/types/integral_constant)
### Constructor ### Constructor
* [`std::integral_constant`](https://en.cppreference.com/w/cpp/types/integral_constant) * mp::value: Aliases to [`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::bool_value: Aliases to [`std::bool_constant`](https://en.cppreference.com/w/cpp/types/integral_constant)
* `mp::lift_value`: Lifts a value to become a metavalue * mp::size_value: Constructs a metavalue with value of type std::size_t
* `mp::lift_value`: Lifts a value of any arbitrary type to become a metavalue
### Conversions ### Conversions
@ -69,9 +70,18 @@ A metavalue is a type of template `std::integral_constant`.
### Operations ### Operations
* `mp::value_equal`: Compares value equality, ignores type. Use `std::is_same` for strict comparison. * `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) * `mp::logic_if`: Like std::conditional but has a bool metavalue as first argument.
* [`std::conjunction`](https://en.cppreference.com/w/cpp/types/conjunction) * `mp::bit_not`: Bitwise not
* [`std::disjunction`](https://en.cppreference.com/w/cpp/types/disjunction) * `mp::bit_and`: Bitwise and
* `mp::bit_or`: Bitwise or
* `mp::bit_xor`: Bitwise xor
* `mp::logic_not`: Logical not
* `mp::logic_and`: Logical conjunction (no short circuiting, always results in a mp:bool_value)
* `mp::logic_or`: Logical disjunction (no short circuiting, always results in a mp:bool_value)
* `mp::conjunction`: Logical conjunction (with short circuiting, preserves type)
* `mp::disjunction`: Logical disjunction (with short circuiting, preserves type)
* `mp::sum`: Sum of values
* `mp::product`: Product of values
`metafunction` `metafunction`
-------------- --------------

View file

@ -1,4 +1,4 @@
/* Ehis file is part of the mp project. /* This file is part of the mp project.
* Copyright (c) 2017 MerryMage * Copyright (c) 2017 MerryMage
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD
*/ */

View file

@ -0,0 +1,20 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/lift_value.h>
namespace 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 mp

View file

@ -0,0 +1,20 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/lift_value.h>
namespace 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 mp

View file

@ -0,0 +1,20 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/lift_value.h>
namespace 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 mp

View file

@ -0,0 +1,20 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/lift_value.h>
namespace 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 mp

View file

@ -0,0 +1,43 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/value.h>
#include <mp/metavalue/logic_if.h>
namespace 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 mp

View file

@ -0,0 +1,43 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/value.h>
#include <mp/metavalue/logic_if.h>
namespace 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 mp

View file

@ -0,0 +1,20 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/value.h>
namespace 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 mp

View file

@ -0,0 +1,21 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <type_traits>
#include <mp/metavalue/value.h>
namespace 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 mp

View file

@ -0,0 +1,20 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/value.h>
namespace 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 mp

View file

@ -0,0 +1,20 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/value.h>
namespace 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 mp

View file

@ -0,0 +1,20 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/lift_value.h>
namespace 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 mp

View file

@ -0,0 +1,20 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <mp/metavalue/lift_value.h>
namespace 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 mp

View file

@ -0,0 +1,31 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <cstddef>
#include <type_traits>
namespace 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 std::size_t (and value v).
template<std::size_t v>
using size_value = value<std::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 mp

View file

@ -13,7 +13,7 @@
namespace mp { namespace mp {
template<class F> template<class F>
struct function_info : public function_info<decltype(&F::operator())> {}; struct function_info : function_info<decltype(&F::operator())> {};
template<class R, class... As> template<class R, class... As>
struct function_info<R(As...)> { struct function_info<R(As...)> {
@ -31,15 +31,15 @@ struct function_info<R(As...)> {
}; };
template<class R, class... As> template<class R, class... As>
struct function_info<R(*)(As...)> : public function_info<R(As...)> {}; struct function_info<R(*)(As...)> : function_info<R(As...)> {};
template<class C, class R, class... As> template<class C, class R, class... As>
struct function_info<R(C::*)(As...)> : public function_info<R(As...)> { struct function_info<R(C::*)(As...)> : function_info<R(As...)> {
using class_type = C; using class_type = C;
}; };
template<class C, class R, class... As> template<class C, class R, class... As>
struct function_info<R(C::*)(As...) const> : public function_info<R(As...)> { struct function_info<R(C::*)(As...) const> : function_info<R(As...)> {
using class_type = C; using class_type = C;
}; };

View file

@ -5,16 +5,16 @@
#pragma once #pragma once
#include <type_traits> #include <mp/metavalue/value.h>
namespace mp { namespace mp {
/// Is type T an instance of template class C? /// Is type T an instance of template class C?
template <template <class...> class, class> template <template <class...> class, class>
struct is_instance_of_template : public std::false_type {}; struct is_instance_of_template : false_type {};
template <template <class...> class C, class... As> template <template <class...> class C, class... As>
struct is_instance_of_template<C, C<As...>> : public std::true_type {}; struct is_instance_of_template<C, C<As...>> : true_type {};
/// Is type T an instance of template class C? /// Is type T an instance of template class C?
template<template <class...> class C, class T> template<template <class...> class C, class T>

View file

@ -1,11 +1,11 @@
/* Ehis file is part of the mp project. /* This file is part of the mp project.
* Copyright (c) 2017 MerryMage * Copyright (c) 2017 MerryMage
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD
*/ */
#pragma once #pragma once
#include <type_traits> #include <mp/metavalue/value.h>
namespace mp { namespace mp {
@ -15,7 +15,7 @@ struct contains;
template<template<class...> class LT, class... Ts, class T> template<template<class...> class LT, class... Ts, class T>
struct contains<LT<Ts...>, T> struct contains<LT<Ts...>, T>
: public std::bool_constant<(false || ... || std::is_same_v<Ts, T>)> : bool_value<(false || ... || std::is_same_v<Ts, T>)>
{}; {};
/// Does list L contain an element which is same as type T? /// Does list L contain an element which is same as type T?

View file

@ -0,0 +1,34 @@
/* This file is part of the mp project.
* Copyright (c) 2020 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <cstddef>
#include <type_traits>
namespace 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 mp

View file

@ -7,17 +7,83 @@
#include <type_traits> #include <type_traits>
#include <mp/metavalue/bit_and.h>
#include <mp/metavalue/bit_not.h>
#include <mp/metavalue/bit_or.h>
#include <mp/metavalue/bit_xor.h>
#include <mp/metavalue/conjunction.h>
#include <mp/metavalue/disjunction.h>
#include <mp/metavalue/lift_value.h> #include <mp/metavalue/lift_value.h>
#include <mp/metavalue/logic_and.h>
#include <mp/metavalue/logic_not.h>
#include <mp/metavalue/logic_or.h>
#include <mp/metavalue/product.h>
#include <mp/metavalue/sum.h>
#include <mp/metavalue/value.h>
#include <mp/metavalue/value_cast.h> #include <mp/metavalue/value_cast.h>
#include <mp/metavalue/value_equal.h> #include <mp/metavalue/value_equal.h>
using namespace mp; using namespace 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 // lift_value
static_assert(std::is_same_v<lift_value<3>, std::integral_constant<int, 3>>); 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>); 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 // value_cast
static_assert(std::is_same_v<value_cast<int, std::true_type>, std::integral_constant<int, 1>>); static_assert(std::is_same_v<value_cast<int, std::true_type>, std::integral_constant<int, 1>>);

View file

@ -10,10 +10,13 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <mp/metavalue/value.h>
#include <mp/typelist/append.h> #include <mp/typelist/append.h>
#include <mp/typelist/cartesian_product.h> #include <mp/typelist/cartesian_product.h>
#include <mp/typelist/concat.h> #include <mp/typelist/concat.h>
#include <mp/typelist/contains.h> #include <mp/typelist/contains.h>
#include <mp/typelist/drop.h>
#include <mp/typelist/get.h> #include <mp/typelist/get.h>
#include <mp/typelist/head.h> #include <mp/typelist/head.h>
#include <mp/typelist/length.h> #include <mp/typelist/length.h>
@ -60,6 +63,14 @@ static_assert(!contains_v<list<>, int>);
static_assert(!contains_v<list<double>, int>); static_assert(!contains_v<list<double>, int>);
static_assert(contains_v<list<double, int>, 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 // get
static_assert(std::is_same_v<get<0, list<int, double>>, int>); static_assert(std::is_same_v<get<0, list<int, double>>, int>);
@ -81,13 +92,13 @@ static_assert(length_v<list<int, int, int>> == 3);
static_assert( static_assert(
std::is_same_v< std::is_same_v<
lift_sequence<std::make_index_sequence<3>>, 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>> list<size_value<0>, size_value<1>, size_value<2>>
> >
); );
// lower_to_tuple // 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<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)); static_assert(lower_to_tuple_v<list<std::true_type, std::false_type>> == std::make_tuple(true, false));
// prepend // prepend