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: 
`std::conditional_t` is to select between two types, but when `T = int` then `T::result_type` is not a type. You can use sfinae:

```
#include <type_traits>

template <typename T, typename = void>
struct result_type_or_void {
    using type = void;
};
template <typename T>
struct result_type_or_void<T,std::void_t<typename T::result_type>> {
    using type = typename T::result_type;
};

template<class T>
struct ResultType
{
    using type = typename result_type_or_void<T>::type;
};

struct Test {
    using result_type = int;
};

int main() {
    ResultType<int> t;
    static_assert( std::is_same_v<ResultType<int>::type,void>);
    static_assert( std::is_same_v<ResultType<Test>::type,int>);
}

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