Skip to content
Snippets Groups Projects
Commit 7c253fe4 authored by Chandler Carruth's avatar Chandler Carruth
Browse files

Try a completely different approach to this type trait to appease older

compilers. It seems that GCC 4.3 (and likely older) simply aren't going
to do SFINAE on non-type template parameters the way Clang and modern
GCCs do...

Now we detect the implicit conversion to an integer type, and then
blacklist classes, pointers, and floating point types. This seems to
work well enough, and I'm hopeful will return the bots to life.

llvm-svn: 152227
parent bc08fed0
No related branches found
No related tags found
No related merge requests found
...@@ -121,46 +121,44 @@ template <> struct is_integral_impl<unsigned long long> : true_type {}; ...@@ -121,46 +121,44 @@ template <> struct is_integral_impl<unsigned long long> : true_type {};
template <typename T> template <typename T>
struct is_integral : is_integral_impl<T> {}; struct is_integral : is_integral_impl<T> {};
namespace dont_use { /// \brief Metafunction to remove reference from a type.
// Form a return type that can only be instantiated with an integral or enum template <typename T> struct remove_reference { typedef T type; };
// types (or with nullptr_t in C++11). template <typename T> struct remove_reference<T&> { typedef T type; };
template <typename U, U u = U()> struct check_nontype_temp_param_return_type {
char c[2]; /// \brief Metafunction that determines whether the given type is a pointer
}; /// type.
template <typename U> template <typename T> struct is_pointer : false_type {};
check_nontype_temp_param_return_type<U> check_nontype_temp_param(U*); template <typename T> struct is_pointer<T*> : true_type {};
template <typename U> char check_nontype_temp_param(...); template <typename T> struct is_pointer<T* const> : true_type {};
template <typename T> struct is_pointer<T* volatile> : true_type {};
// Form a return type that can only be instantiated with nullptr_t in C++11 template <typename T> struct is_pointer<T* const volatile> : true_type {};
// mode. It's harmless in C++98 mode, but this allows us to filter nullptr_t
// when building in C++11 mode without having to detect that mode for each
// different compiler.
struct nonce {};
template <typename U, nonce* u = U()>
struct check_nullptr_t_like_return_type { char c[2]; };
template <typename U>
check_nullptr_t_like_return_type<U> check_nullptr_t_like(U*);
template <typename U> char check_nullptr_t_like(...);
} // namespace dont_use
/// \brief Metafunction that determines whether the given type is either an /// \brief Metafunction that determines whether the given type is either an
/// integral type or an enumeration type. /// integral type or an enumeration type.
/// ///
/// Note that this accepts potentially more integral types than we whitelist /// Note that this accepts potentially more integral types than we whitelist
/// above for is_integral, it should accept essentially anything the compiler /// above for is_integral because it is based on merely being convertible
/// believes is an integral type. /// implicitly to an integral type.
template <typename T> struct is_integral_or_enum { template <typename T> class is_integral_or_enum {
// Provide an overload which can be called with anything implicitly
// convertible to an unsigned long long. This should catch integer types and
// enumeration types at least. We blacklist classes with conversion operators
// below.
static double check_int_convertible(unsigned long long);
static char check_int_convertible(...);
typedef typename remove_reference<T>::type UnderlyingT;
static UnderlyingT &nonce_instance;
public:
enum { enum {
value = (sizeof(char) != sizeof(dont_use::check_nontype_temp_param<T>(0)) && value = (!is_class<UnderlyingT>::value && !is_pointer<UnderlyingT>::value &&
sizeof(char) == sizeof(dont_use::check_nullptr_t_like<T>(0))) !is_same<UnderlyingT, float>::value &&
!is_same<UnderlyingT, double>::value &&
sizeof(char) != sizeof(check_int_convertible(nonce_instance)))
}; };
}; };
/// \brief Metafunction that determines whether the given type is a pointer
/// type.
template <typename T> struct is_pointer : false_type {};
template <typename T> struct is_pointer<T*> : true_type {};
// enable_if_c - Enable/disable a template based on a metafunction // enable_if_c - Enable/disable a template based on a metafunction
template<bool Cond, typename T = void> template<bool Cond, typename T = void>
struct enable_if_c { struct enable_if_c {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment