dimanche 13 août 2023

SFINAE does not disable one of the functions

I have a packaged_task class which wraps a Callable and has invoke() functions, one if Callable does not take any arguments, and a second one when it does.

I get errors accessing typename traits::template arg<0>::type for the second one, even though it should be disabled by enable_if SFINAE.

Any idea why I am getting this behavior?

#include <functional>
#include <type_traits>
namespace detail
{
    template<typename T, typename Enabler = void>
    struct function_traits;

    template <typename T>
    struct function_traits<T, typename std::enable_if<std::is_class<T>{}>::type> : public function_traits<decltype(&T::operator())>
    {
    };

    template <typename ClassType, typename ReturnType, typename... Args>
    struct function_traits<ReturnType(ClassType::*)(Args...) const>
    {
        using result_type = ReturnType;
        static constexpr auto n_args = sizeof...(Args);

        template<std::size_t I>
        struct arg { using type = typename std::tuple_element<I, std::tuple<Args...>>::type; };

        template<std::size_t I>
        using arg_t = typename arg<I>::type;
    };

    template <typename ReturnType, typename... Args>
    struct function_traits<ReturnType(Args...)>
    {
        using result_type = ReturnType;
        static constexpr auto n_args = sizeof...(Args);

        template<std::size_t I>
        struct arg { using type = typename std::tuple_element<I, std::tuple<Args...>>::type; };

        template<std::size_t I>
        using arg_t = typename arg<I>::type;
    };
}

template<typename Callable>
class packaged_task
{
public:
    using traits = detail::function_traits<Callable>;

    template<std::size_t n_args = traits::n_args>
    typename std::enable_if<n_args == 0>::type
    invoke()
    {
    }

    template<std::size_t n_args = traits::n_args>
    typename std::enable_if<n_args == 1>::type
    invoke(typename traits::template arg<0>::type val)
    {
    }
};
int main()
{
    packaged_task<void()> task;
}

Aucun commentaire:

Enregistrer un commentaire