Question: How to fix this:

```cpp
template<class T>
struct ResultType
{
    using type = std::conditional_t<std::is_class_v<T>, typename T::result_type, void>;
};

```

It cannot be it is supposed to return void, if T is not class type, but instead:

> 
> error: ‘int’ is not a class, struct, or union type
> 24 | using type = std::conditional\_tstd::is\_class\_v<T, typename T::result\_type, void>;
> 
> 
> 

So I need to not try to invoke the false expression, but how?

Answer: 
In the following:

```cpp
using type = std::conditional_t<std::is_class_v<T>, typename T::result_type, void>;

```

The part `typename T::result_type` will fail when `T = int`, because `typename int::result_type` is ill-formed.

You can fix this by using a template specialization instead of `std::conditional` which does the exact same thing but avoids doing `T::result_type` when `T` is not a class type:

```cpp
#include <type_traits>

template <typename T, typename = void>
struct ResultType;

template <typename T>
struct ResultType<T, std::enable_if_t<!std::is_class_v<T>>> {
    using type = void;
};

template<typename T>
struct ResultType<T, std::enable_if_t<std::is_class_v<T>>> {
    using type = typename T::result_type;
};

// ...

struct X {
    using result_type = int;
};

int main() {
    static_assert(std::is_same_v<typename ResultType<X>::type, typename X::result_type>, "FAIL!");
    static_assert(std::is_same_v<typename ResultType<int>::type, void>, "FAIL!");
}

```
The failure is because `std::conditional` *selects* one of the two type expressions -- but by this point the type expressions are already evaluated. Since `int` is not a class, and does not have `result_type` -- it errors.

As others have pointed out, this can be resolved with SFINAE via `enable_if` or `void_t` -- but one other approach is to leverage function overloads with expression SFINAE instead of requiring partial specializations:

```cpp
template <typename T, typename Default = void>
class ResultType
{
    static auto test(...) -> Default;
    template <typename U>
    static auto test(const U&) -> typename U::result_type;
public:
    using type = decltype(test(std::declval<T>()));
};

```

`[Live Example](https://godbolt.org/z/dTfb3Wz1a)`

When `T` is a type that defines `result_type`, the `test(const U&)` branch is enabled and is selected for overload resolution; otherwise `test(...)` is selected for everything else and becomes `Default` (`void`, in this case).

The type is then deduced with `decltype` by evaluating the expression to see which overload gets selected.