refs #628 Use expression SFINAE and the void_t trick to simplify some type traits.

This commit is contained in:
Mathew Sutcliffe
2016-03-25 19:01:07 +00:00
parent f159bdb5bf
commit 7ce1b268df
8 changed files with 117 additions and 85 deletions

View File

@@ -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.