1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
/* SPDX-License-Identifier: MIT */
/* Copyright © 2020 Max Bachmann */
#pragma once
#include <rapidfuzz/details/types.hpp>
#include <iterator>
#include <utility>
namespace rapidfuzz {
namespace detail {
template <typename T>
auto inner_type(T const*) -> T;
template <typename T>
auto inner_type(T const&) -> typename T::value_type;
} // namespace detail
template <typename T>
using char_type = decltype(detail::inner_type(std::declval<T const&>()));
/* backport of std::iter_value_t from C++20
* This does not cover the complete functionality, but should be enough for
* the use cases in this library
*/
template <typename T>
using iter_value_t = typename std::iterator_traits<T>::value_type;
// taken from
// https://stackoverflow.com/questions/16893992/check-if-type-can-be-explicitly-converted
template <typename From, typename To>
struct is_explicitly_convertible {
template <typename T>
static void f(T);
template <typename F, typename T>
static constexpr auto test(int /*unused*/) -> decltype(f(static_cast<T>(std::declval<F>())), true)
{
return true;
}
template <typename F, typename T>
static constexpr auto test(...) -> bool
{
return false;
}
static bool const value = test<From, To>(0);
};
template <bool B, class T = void>
using rf_enable_if_t = typename std::enable_if<B, T>::type;
} // namespace rapidfuzz
|