rec/fplus/internal/meta.hpp
2020-03-18 14:42:46 +08:00

183 lines
5.5 KiB
C++
Executable File

// Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
// https://github.com/Dobiasd/FunctionalPlus
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#pragma once
#include <type_traits>
namespace fplus
{
namespace internal
{
// C++14 compatible void_t (http://en.cppreference.com/w/cpp/types/void_t)
template <typename... Ts>
struct make_void
{
using type = void;
};
template <typename... Ts>
using void_t = typename make_void<Ts...>::type;
// Sometimes you don't want to use std::decay_t, and the temptation of short
// writing can be huge...
template <typename T>
using uncvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
// disjunction/conjunction/negation, useful to short circuit SFINAE checks
// Use with parsimony, MSVC 2015 can have ICEs quite easily
template <typename...>
struct disjunction : std::false_type
{
};
template <typename B1>
struct disjunction<B1> : B1
{
};
template <typename B1, typename... Bn>
struct disjunction<B1, Bn...>
: std::conditional<bool(B1::value), B1, disjunction<Bn...>>::type
{
};
template <typename...>
struct conjunction : std::true_type
{
};
template <typename B1>
struct conjunction<B1> : B1
{
};
template <typename B1, typename... Bn>
struct conjunction<B1, Bn...>
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type
{
};
template <typename B>
struct negation : std::integral_constant<bool, !bool(B::value)>
{
};
// non short-circuiting meta functions
// source: https://stackoverflow.com/a/27221517/4116453
template <bool...>
struct bool_pack;
template <bool... Values>
struct all_of
: std::is_same<bool_pack<Values..., true>, bool_pack<true, Values...>>
{
};
// there seems to be a bug in libc++'s std::is_function
// provide our own (cppreference one)
// (the MSVC implementation seems correct)
#ifndef _MSC_VER
#define PROVIDE_IS_FUNCTION_POLYFILL
#endif
#ifndef PROVIDE_IS_FUNCTION_POLYFILL
template<class... Any>
using is_function = std::is_function<Any...>;
#else //PROVIDE_IS_FUNCTION_POLYFILL
// primary template
template<class>
struct is_function : std::false_type { };
// specialization for regular functions
template<class Ret, class... Args>
struct is_function<Ret(Args...)> : std::true_type {};
// specialization for variadic functions such as std::printf
template<class Ret, class... Args>
struct is_function<Ret(Args...,...)> : std::true_type {};
// specialization for function types that have cv-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...) const> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) const> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) volatile> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) const volatile> : std::true_type {};
// specialization for function types that have ref-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...) &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) const &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) volatile &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) const volatile &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) const &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) volatile &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...,...) const volatile &&> : std::true_type {};
#endif //PROVIDE_IS_FUNCTION_POLYFILL
template <typename>
struct reverse_integer_sequence_impl;
template <typename T>
struct reverse_integer_sequence_impl<std::integer_sequence<T>>
: std::integer_sequence<T>
{
};
template <typename T, T... Ints>
struct reverse_integer_sequence_impl<std::integer_sequence<T, Ints...>>
: std::integer_sequence<T, sizeof...(Ints) - 1 - Ints...>
{
};
template <typename Seq>
using reverse_integer_sequence = reverse_integer_sequence_impl<Seq>;
template <typename T, T N>
using make_reverse_integer_sequence =
reverse_integer_sequence<std::make_integer_sequence<T, N>>;
template <std::size_t... Idx>
using reverse_index_sequence =
reverse_integer_sequence<std::index_sequence<Idx...>>;
template <std::size_t N>
using make_reverse_index_sequence =
make_reverse_integer_sequence<std::size_t, N>;
}
}