2012-05-25 15:19:07 +10:00
|
|
|
/*
|
2015-04-13 18:05:28 +10:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2012-05-25 15:19:07 +10:00
|
|
|
*
|
2015-04-13 18:05:28 +10:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
2012-05-25 15:19:07 +10:00
|
|
|
*
|
2017-09-06 13:31:02 +10:00
|
|
|
* Copyright 2012-2017 Danny Robson <danny@nerdcruft.net>
|
2012-05-25 15:19:07 +10:00
|
|
|
*/
|
|
|
|
|
2017-09-08 14:10:57 +10:00
|
|
|
#ifndef CRUFT_UTIL_TYPES_TRAITS_HPP
|
|
|
|
#define CRUFT_UTIL_TYPES_TRAITS_HPP
|
2012-05-25 15:19:07 +10:00
|
|
|
|
2015-03-10 22:52:17 +11:00
|
|
|
#include <memory>
|
2014-07-15 19:51:23 +10:00
|
|
|
#include <type_traits>
|
|
|
|
|
2017-09-08 14:10:57 +10:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// applies a series of type-modifiers to a provided type.
|
|
|
|
///
|
|
|
|
/// modifiers are applied in the order they are provided.
|
|
|
|
///
|
|
|
|
/// use without any modifiers results in the identity modifier.
|
|
|
|
namespace util {
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
template <typename TypeT, template <typename> class ...ModifierT>
|
|
|
|
struct chain;
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
template <typename TypeT>
|
|
|
|
struct chain<TypeT> { using type = TypeT; };
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
template <
|
|
|
|
typename TypeT,
|
|
|
|
template <typename> class HeadT,
|
|
|
|
template <typename> class ...TailT
|
|
|
|
>
|
|
|
|
struct chain<TypeT, HeadT, TailT...> : public chain<
|
|
|
|
typename HeadT<TypeT>::type,
|
|
|
|
TailT...
|
|
|
|
> { };
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
template <typename T, template <typename> class ...Args>
|
|
|
|
using chain_t = typename chain<T, Args...>::type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2012-05-25 15:19:07 +10:00
|
|
|
template <typename T> struct is_dereferencable : std::false_type { };
|
|
|
|
template <typename T> struct is_dereferencable<T*> : std::true_type { };
|
|
|
|
template <typename T> struct is_dereferencable<std::unique_ptr<T>> : std::true_type { };
|
|
|
|
template <typename T> struct is_dereferencable<std::shared_ptr<T>> : std::true_type { };
|
|
|
|
template <typename T> struct is_dereferencable<std::weak_ptr<T>> : std::true_type { };
|
|
|
|
|
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2012-05-25 15:19:07 +10:00
|
|
|
template <typename T> struct dereferenced_type {
|
|
|
|
typedef typename std::enable_if<
|
|
|
|
std::is_pointer<T>::value,
|
|
|
|
std::remove_pointer<T>
|
|
|
|
>::type type;
|
|
|
|
};
|
|
|
|
|
2014-07-15 19:51:23 +10:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2012-05-25 15:19:07 +10:00
|
|
|
template <typename T> struct dereferenced_type<std::unique_ptr<T>> { typedef T type; };
|
|
|
|
template <typename T> struct dereferenced_type<std::shared_ptr<T>> { typedef T type; };
|
|
|
|
template <typename T> struct dereferenced_type<std::weak_ptr<T>> { typedef T type; };
|
|
|
|
|
2012-05-25 15:30:11 +10:00
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2015-02-18 02:33:51 +11:00
|
|
|
/// find the unsigned version of a type if one exists
|
2015-02-17 16:20:15 +11:00
|
|
|
template <typename T>
|
|
|
|
struct try_unsigned
|
|
|
|
{
|
2012-05-25 15:30:11 +10:00
|
|
|
typedef typename std::make_unsigned<T>::type type;
|
|
|
|
};
|
2015-02-17 16:20:15 +11:00
|
|
|
|
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
//-----------------------------------------------------------------------------
|
2015-02-17 16:20:15 +11:00
|
|
|
template <> struct try_unsigned<double> { typedef double type; };
|
|
|
|
template <> struct try_unsigned<float > { typedef float type; };
|
2012-05-25 15:30:11 +10:00
|
|
|
|
2014-07-15 19:51:42 +10:00
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2015-03-20 01:32:28 +11:00
|
|
|
/// find the signed version of a type if one exists
|
|
|
|
template <typename T>
|
|
|
|
struct try_signed
|
|
|
|
{
|
|
|
|
typedef typename std::make_signed<T>::type type;
|
|
|
|
};
|
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2015-03-20 01:32:28 +11:00
|
|
|
template <> struct try_signed<double> { typedef double type; };
|
|
|
|
template <> struct try_signed<float > { typedef float type; };
|
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2015-02-18 02:33:51 +11:00
|
|
|
/// checks if a type can be converted in all cases without modification
|
2014-07-15 19:51:42 +10:00
|
|
|
template <typename T, typename U> struct is_lossless_cast : std::enable_if<
|
|
|
|
std::is_integral<T>::value &&
|
|
|
|
std::is_integral<U>::value &&
|
|
|
|
std::is_signed<T>::value == std::is_signed<U>::value &&
|
|
|
|
sizeof (T) <= sizeof (U),
|
|
|
|
|
|
|
|
std::true_type
|
|
|
|
>::value { };
|
|
|
|
|
2015-03-10 22:52:17 +11:00
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2017-09-06 13:31:02 +10:00
|
|
|
template <typename T> struct remove_restrict { using type = T; };
|
|
|
|
template <typename T> struct remove_restrict<T *restrict> { using type = T*; };
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
using remove_restrict_t = typename remove_restrict<T>::type;
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// removes the noexcept type specifier from invokable types
|
2015-03-10 22:52:17 +11:00
|
|
|
template <typename T>
|
2017-09-06 13:31:02 +10:00
|
|
|
struct remove_noexcept
|
|
|
|
{ using type = T; };
|
2015-03-10 22:52:17 +11:00
|
|
|
|
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
//-----------------------------------------------------------------------------
|
2017-09-06 13:31:02 +10:00
|
|
|
template <typename ResultT, typename ...Args>
|
|
|
|
struct remove_noexcept<ResultT(&)(Args...) noexcept> {
|
|
|
|
using type = ResultT(&)(Args...);
|
2015-03-10 22:52:17 +11:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
//-----------------------------------------------------------------------------
|
2017-09-06 13:31:02 +10:00
|
|
|
template <typename ResultT, typename ...Args>
|
|
|
|
struct remove_noexcept<ResultT(*)(Args...) noexcept> {
|
|
|
|
using type = ResultT(*)(Args...);
|
2015-03-10 22:52:17 +11:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-09-06 13:31:02 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
template <typename ClassT, typename ResultT, typename ...Args>
|
|
|
|
struct remove_noexcept<ResultT(ClassT::*)(Args...) noexcept> {
|
|
|
|
using type = ResultT(ClassT::*)(Args...);
|
|
|
|
};
|
|
|
|
|
2016-03-16 19:27:39 +11:00
|
|
|
|
2017-09-06 13:31:02 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
2016-03-16 19:27:39 +11:00
|
|
|
template <typename T>
|
2017-09-06 13:31:02 +10:00
|
|
|
using remove_noexcept_t = typename remove_noexcept<T>::type;
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// type traits class for querying invokable type return values and argument
|
|
|
|
/// types.
|
|
|
|
///
|
|
|
|
/// if the type is invokable the alias `return_type' will be defined for the
|
|
|
|
/// return type, and the alias tuple `argument_types' will be defined for the
|
|
|
|
/// arguments;
|
|
|
|
template <typename T>
|
|
|
|
struct func_traits : public func_traits<remove_noexcept_t<T>> { };
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
template <typename ClassT, typename ResultT, typename ...Args>
|
|
|
|
struct func_traits<ResultT(ClassT::*)(Args...) const> {
|
|
|
|
using return_type = ResultT;
|
|
|
|
using argument_types = std::tuple<Args...>;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
template <typename ResultT, typename ...Args>
|
|
|
|
struct func_traits<ResultT(*)(Args...)> {
|
|
|
|
using return_type = ResultT;
|
|
|
|
using argument_types = std::tuple<Args...>;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
template <typename ResultT, typename ...Args>
|
|
|
|
struct func_traits<ResultT(&)(Args...)> {
|
|
|
|
using return_type = ResultT;
|
|
|
|
using argument_types = std::tuple<Args...>;
|
|
|
|
};
|
2016-03-16 19:27:39 +11:00
|
|
|
|
|
|
|
|
2012-05-25 15:19:07 +10:00
|
|
|
#endif
|