Reactor: Work around new MSVC brokenness.

Complex SFINAE expressions appear to be broken on the latest release of MSVC 2017.

MSVC++ 14.15 (Visual Studio 2017 version 15.8):
The parent change compiles fine.

MSVC++ 14.16 (Visual Studio 2017 version 15.9):
 `error C2039: 'type': is not a member of 'std'` for some CToReactorPtr specializations that use `std::enable_if`.

Replacing these `typename std::enable_if<T>::type` with `enable_if_t<T>` works around the issue (while also making the template expressions easier to read).

I was unable to find an existing MSVC bug report for this problem, and so I will create one.

Bug: swiftshader:141
Change-Id: I7e953dbc719d7cb656aa7f16656c3f86ffad5522
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/38688
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Reactor/Traits.hpp b/src/Reactor/Traits.hpp
index 722b9a4..ccef628 100644
--- a/src/Reactor/Traits.hpp
+++ b/src/Reactor/Traits.hpp
@@ -43,6 +43,12 @@
 	template<class T> class LValue;
 	template<class T> class RValue;
 
+	// enabled_if_t is identical to C++14's std::enable_if_t.
+	// std::enable_if_t was introduced in C++14, but Reactor must support
+	// C++11.
+	template<bool Condition, class TrueType = void>
+	using enable_if_t = typename std::enable_if<Condition, TrueType>::type;
+
 	// IsDefined<T>::value is true if T is a valid type, otherwise false.
 	template <typename T, typename Enable = void>
 	struct IsDefined
@@ -51,7 +57,7 @@
 	};
 
 	template <typename T>
-	struct IsDefined<T, typename std::enable_if<(sizeof(T)>0)>::type>
+	struct IsDefined<T, enable_if_t<(sizeof(T)>0)> >
 	{
 		static constexpr bool value = true;
 	};
@@ -81,6 +87,11 @@
 	// TODO: Long has no constructor that takes a uint64_t
 	template<> struct CToReactor<uint64_t>	{ using type = Long;  /* static Long   cast(uint64_t); */ };
 
+	// HasReactorType<T>::value resolves to true iff there exists a
+	// CToReactorT specialization for type T.
+	template<typename T>
+	using HasReactorType = IsDefined< CToReactorT<T> >;
+
 	// CToReactorPtr<T>::type resolves to the corresponding Reactor Pointer<>
 	// type for T*.
 	// For T types that have a CToReactorT<> specialization,
@@ -94,7 +105,7 @@
 
 	// CToReactorPtr specialization for T types that have a CToReactorT<>
 	// specialization.
-	template<typename T> struct CToReactorPtr<T, typename std::enable_if< IsDefined< CToReactorT<T> >::value>::type >
+	template<typename T> struct CToReactorPtr<T, enable_if_t< HasReactorType<T>::value > >
 	{
 		using type = Pointer< CToReactorT<T> >;
 		static inline type cast(const T* v); // implemented in Traits.inl
@@ -112,7 +123,7 @@
 	// Maps to Pointer<Byte>.
 	// Drops the 'const' qualifier from the cast() method to avoid warnings
 	// about const having no meaning for function types.
-	template<typename T> struct CToReactorPtr<T, typename std::enable_if< std::is_function<T>::value >::type >
+	template<typename T> struct CToReactorPtr<T, enable_if_t< std::is_function<T>::value > >
 	{
 		using type = Pointer<Byte>;
 		static inline type cast(T* v); // implemented in Traits.inl
@@ -125,7 +136,7 @@
 	// CToReactorT<T*>::type resolves to Pointer< CToReactorT<T> >, otherwise
 	// CToReactorT<T*>::type resolves to Pointer<Byte>.
 	template<typename T>
-	struct CToReactor<T, typename std::enable_if<std::is_pointer<T>::value>::type>
+	struct CToReactor<T, enable_if_t<std::is_pointer<T>::value> >
 	{
 		using elem = typename std::remove_pointer<T>::type;
 		using type = CToReactorPtrT<elem>;
@@ -134,7 +145,7 @@
 
 	// CToReactor specialization for enum types.
 	template<typename T>
-	struct CToReactor<T, typename std::enable_if<std::is_enum<T>::value>::type>
+	struct CToReactor<T, enable_if_t<std::is_enum<T>::value> >
 	{
 		using underlying = typename std::underlying_type<T>::type;
 		using type = CToReactorT<underlying>;
@@ -143,35 +154,35 @@
 
 	// IsRValue::value is true if T is of type RValue<X>, where X is any type.
 	template <typename T, typename Enable = void> struct IsRValue { static constexpr bool value = false; };
-	template <typename T> struct IsRValue<T, typename std::enable_if<IsDefined<typename T::rvalue_underlying_type>::value>::type> { static constexpr bool value = true; };
+	template <typename T> struct IsRValue<T, enable_if_t<IsDefined<typename T::rvalue_underlying_type>::value> > { static constexpr bool value = true; };
 
 	// IsLValue::value is true if T is of, or derives from type LValue<T>.
 	template <typename T> struct IsLValue { static constexpr bool value = std::is_base_of<LValue<T>, T>::value; };
 
 	// IsReference::value is true if T is of type Reference<X>, where X is any type.
 	template <typename T, typename Enable = void> struct IsReference { static constexpr bool value = false; };
-	template <typename T> struct IsReference<T, typename std::enable_if<IsDefined<typename T::reference_underlying_type>::value>::type> { static constexpr bool value = true; };
+	template <typename T> struct IsReference<T, enable_if_t<IsDefined<typename T::reference_underlying_type>::value> > { static constexpr bool value = true; };
 
 	// ReactorTypeT<T> returns the LValue Reactor type for T.
 	// T can be a C-type, RValue or LValue.
 	template<typename T, typename ENABLE = void> struct ReactorType;
 	template<typename T> using ReactorTypeT = typename ReactorType<T>::type;
-	template<typename T> struct ReactorType<T, typename std::enable_if<IsDefined<CToReactorT<T>>::value>::type>
+	template<typename T> struct ReactorType<T, enable_if_t<IsDefined<CToReactorT<T>>::value> >
 	{
 		using type = CToReactorT<T>;
 		static type cast(T v) { return CToReactor<T>::cast(v); }
 	};
-	template<typename T> struct ReactorType<T, typename std::enable_if<IsRValue<T>::value>::type>
+	template<typename T> struct ReactorType<T, enable_if_t<IsRValue<T>::value> >
 	{
 		using type = typename T::rvalue_underlying_type;
 		static type cast(T v) { return type(v); }
 	};
-	template<typename T> struct ReactorType<T, typename std::enable_if<IsLValue<T>::value>::type>
+	template<typename T> struct ReactorType<T, enable_if_t<IsLValue<T>::value> >
 	{
 		using type = T;
 		static type cast(T v) { return type(v); }
 	};
-	template<typename T> struct ReactorType<T, typename std::enable_if<IsReference<T>::value>::type>
+	template<typename T> struct ReactorType<T, enable_if_t<IsReference<T>::value> >
 	{
 		using type = T;
 		static type cast(T v) { return type(v); }
diff --git a/src/Reactor/Traits.inl b/src/Reactor/Traits.inl
index fd40f5b..2e10568 100644
--- a/src/Reactor/Traits.inl
+++ b/src/Reactor/Traits.inl
@@ -29,7 +29,7 @@
 	// specialization.
 	template<typename T>
 	Pointer<CToReactorT<T>>
-	CToReactorPtr<T, typename std::enable_if< IsDefined< CToReactorT<T> >::value>::type >::cast(const T* v)
+	CToReactorPtr<T, enable_if_t< HasReactorType<T>::value > >::cast(const T* v)
 	{
 		return type(v);
 	}
@@ -43,7 +43,7 @@
 	// CToReactorPtrT specialization for function pointer types.
 	template<typename T>
 	Pointer<Byte>
-	CToReactorPtr<T, typename std::enable_if< std::is_function<T>::value >::type>::cast(T* v)
+	CToReactorPtr<T, enable_if_t< std::is_function<T>::value > >::cast(T* v)
 	{
 		return ConstantPointer(v);
 	}
@@ -51,7 +51,7 @@
 	// CToReactor specialization for pointer types.
 	template<typename T>
 	CToReactorPtrT<typename std::remove_pointer<T>::type>
-	CToReactor<T, typename std::enable_if<std::is_pointer<T>::value>::type>::cast(T v)
+	CToReactor<T, enable_if_t<std::is_pointer<T>::value> >::cast(T v)
 	{
 		return CToReactorPtr<elem>::cast(v);
 	}
@@ -59,7 +59,7 @@
 	// CToReactor specialization for enum types.
 	template<typename T>
 	CToReactorT<typename std::underlying_type<T>::type>
-	CToReactor<T, typename std::enable_if<std::is_enum<T>::value>::type>::cast(T v)
+	CToReactor<T, enable_if_t<std::is_enum<T>::value> >::cast(T v)
 	{
 		return CToReactor<underlying>::cast(v);
 	}