Question: I have a problem similar to this one: [SFINAE tried with bool gives compiler error: "template argument ‘T::value’ involves template parameter"](https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol)

I want to define a trait that tells if a complex representation is an array of structs, where real values are never AoS hence no user defined specilization should be required, but for complex you'd always need one: 

```
/**
 * Evaluates to a true type if the given complex type is an Array of Structs, false otherwise
 * Defaults to false for Real values
 */
template< typename T, bool T_isComplex = IsComplex<T>::value >
struct IsAoS: std::false_type{};

/**
 * Undefined for (unknown) complex types
 */
template< typename T >
struct IsAoS< T, true >;

```

Specializations are done in the std-way by deriving from std::true/false\_type.

The problem is: With this implementation I get the "template argument involves template parameter(s)" error (which is explained in the linked question) but if i switch to types (ommit "::value" in first template and change true to true\_type in 2nd) Complex types won't match the 2nd template anymore because the only derive from std::true\_type and ARE NOT std::true\_type.

Only solution I can think of is using expression SFINAE and change the 2nd parameter of the main template to default void and an enable\_if for the real case (isComplex==false). Anything better?

Answer: 
On the assumption that `IsAoS<T>`'s desired behavior is:

* If `IsComplex<T>::value` is `false`, it defaults to `false_type`;
* Otherwise, it is an error unless the user provides a specialization.

It's straightforward to implement with a `static_assert`; no default template argument needed:

```
template< typename T >
struct IsAoS: std::false_type {
    static_assert(!IsComplex<T>::value, "A user specialization must be provided for Complex types");
};

```

---

If you want the default argument trickery, just use a wrapper layer:

```
namespace detail {

    template< typename T, bool T_isComplex = IsComplex<T>::value >
    struct IsAoS_impl: std::false_type{};

    /**
     * Undefined for (unknown) complex types
     */
    template< typename T >
    struct IsAoS_impl< T, true >;
}

template<class T> struct IsAoS : detail::IsAoS_impl<T> {};

```

Users should just specialize `IsAoS`.
If I understand correctly, you want:

```
template<class> struct IsComplex_impl  {using type = std::false_type;};
template<class T> struct IsComplex_impl<std::complex<T>> {using type = std::true_type;};

template <typename T>
using IsComplex =  typename IsComplex_impl<T>::type;

// Declaration only
template<typename T, typename T_isComplex = IsComplex<T>>
struct IsAoS;

// general case
template< typename T >
struct IsAoS< T, std::false_type >: std::false_type{};

// specialization for complex<double>
template<>
struct IsAoS< std::complex<double>>: std::true_type{};

```

[Live Demo](https://ideone.com/6gNRbW)

or with same signature:

```
template<class> struct IsComplex_impl : std::false_type {};
template<class T> struct IsComplex_impl<std::complex<T>> : std::true_type {};

template <typename T>
constexpr bool IsComplex() {return IsComplex_impl<T>::value;}

// Declaration only
template<typename T, bool T_isComplex = IsComplex<T>()>
struct IsAoS;

// general case
template< typename T >
struct IsAoS< T, false>: std::false_type{};

// specialization for complex<double>
template<>
struct IsAoS< std::complex<double>>: std::true_type{};

```

[Live Demo](https://ideone.com/qQqeax)