mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-18 11:25:33 +08:00
refs #628 Use expression SFINAE and the void_t trick to simplify some type traits.
This commit is contained in:
@@ -12,35 +12,36 @@
|
||||
#ifndef BLACKMISC_INHERITANCE_TRAITS_H
|
||||
#define BLACKMISC_INHERITANCE_TRAITS_H
|
||||
|
||||
#include "typetraits.h"
|
||||
#include <QMetaType>
|
||||
#include <type_traits>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
class CEmpty;
|
||||
class CPropertyIndex;
|
||||
|
||||
/*!
|
||||
* If T has a member typedef base_type, this trait will obtain it, otherwise void.
|
||||
*/
|
||||
template <class T>
|
||||
class BaseOf
|
||||
template <typename T, typename = void_t<>>
|
||||
struct BaseOf
|
||||
{
|
||||
//template <typename U> static typename U::base_type *test(int);
|
||||
template <typename U> static typename U::base_type *test(std::enable_if_t<! std::is_same<typename U::base_type, CEmpty>::value, int>);
|
||||
template <typename U> static void *test(...);
|
||||
|
||||
public:
|
||||
//! The declared base_type of T, or void if there is none.
|
||||
using type = std::remove_pointer_t<decltype(test<T>(0))>;
|
||||
using type = void; //!< void
|
||||
};
|
||||
//! \cond
|
||||
template <typename T>
|
||||
struct BaseOf<T, void_t<typename T::base_type>>
|
||||
{
|
||||
using type = typename T::base_type; //!< T::base_type
|
||||
};
|
||||
//! \endcond
|
||||
|
||||
/*!
|
||||
* It T has a member typedef base_type which is a registered metatype, this trait will obtain it, otherwise void.
|
||||
*/
|
||||
template <class T>
|
||||
class MetaBaseOf
|
||||
struct MetaBaseOf
|
||||
{
|
||||
public:
|
||||
//! Type of T::base_type, or void if not declared.
|
||||
using type = std::conditional_t<QMetaTypeId<typename BaseOf<T>::type>::Defined, typename BaseOf<T>::type, void>;
|
||||
};
|
||||
@@ -48,22 +49,18 @@ namespace BlackMisc
|
||||
/*!
|
||||
* If T has a member typedef base_type which has a member propertyByIndex, this trait will obtain it, otherwise void.
|
||||
*/
|
||||
template <class T>
|
||||
class IndexBaseOf
|
||||
template <typename T, typename = void_t<>>
|
||||
struct IndexBaseOf
|
||||
{
|
||||
// http://en.wikibooks.org/wiki/More_C++_Idioms/Member_Detector
|
||||
struct Empty {};
|
||||
struct Fallback { int propertyByIndex; };
|
||||
template <int Fallback:: *> struct int_t { using type = int; };
|
||||
template <typename U> struct Derived : public Fallback, public std::conditional_t<std::is_void<U>::value, Empty, U> {};
|
||||
|
||||
template <typename U> static void test(typename int_t<&Derived<U>::propertyByIndex>::type);
|
||||
template <typename U> static U test(...);
|
||||
|
||||
public:
|
||||
//! Type of T::base_type, or void if not declared.
|
||||
using type = decltype(test<typename BaseOf<T>::type>(0));
|
||||
using type = void; //!< void
|
||||
};
|
||||
//! \cond
|
||||
template <typename T>
|
||||
struct IndexBaseOf<T, void_t<decltype(std::declval<typename T::base_type>().propertyByIndex(std::declval<CPropertyIndex>()))>>
|
||||
{
|
||||
using type = typename T::base_type; //!< T::base_type
|
||||
};
|
||||
//! \endcond
|
||||
|
||||
/*!
|
||||
* Alias for typename BaseOf<T>::type.
|
||||
|
||||
Reference in New Issue
Block a user