c++templates

Why do I need an Enable type parameter when using std::enable_if


According to the examples in std::enable_if documentation, this compiles:

template <typename T, typename Enable = void>
struct transform {
    T operator()(nlohmann::json &data);
};

template <typename T>
struct transform<T, std::enable_if_t<std::is_integral_v<T>>> {
    T operator()(nlohmann::json &data) {
        ...
    }
};

What I don't understand is why I need the Enable type parameter when enable_if_t can evaluate to a type. In other words, why won't this compile:

template <typename T>
struct transform {
    T operator()(nlohmann::json &data);
};

template <typename T>
struct transform<std::enable_if_t<std::is_integral_v<T>, T>> {
    T operator()(nlohmann::json &data) {
        ...
    }
};

Solution

  • This form of class template is considered partial specialization:

    template <typename T>
    struct transform<std::enable_if_t<std::is_integral_v<T>, T>> {
        T operator()(nlohmann::json &data) {
            ...
        }
    };
    

    The problem here is that std::enable_if_t<std::is_integral_v<T>, T> puts T in the so-called non-deduced context, so it's essentially impossible for the compiler to conclude which T this specialisation correspond to.