11

私は is_callable 特性を次のように定義しています:

#ifndef IS_CALLABLE_HPP
#define IS_CALLABLE_HPP

#include <type_traits>

namespace is_callable_detail
{
    struct no   {};
    struct yes  { no x[2]; };

    template<bool CallableArgs, typename Callable, typename ReturnType, typename ...Args>
    struct check_return
    {
        static const bool value = std::is_convertible<decltype(std::declval<Callable>()(std::declval<Args>()...)), ReturnType>::value;
    };

    template<typename Callable, typename ReturnType, typename ...Args>
    struct check_return<false, Callable, ReturnType, Args...>
    {
        static const bool value = false;
    };
}

template<typename Callable, typename Function>
struct is_callable;

template<typename Callable, typename ReturnType, typename ...Args>
struct is_callable<Callable, ReturnType(Args...)>
{
    private:
        template<typename T>
        static is_callable_detail::yes check(decltype(std::declval<T>()(std::declval<Args>()...)) *);
        template<typename T>
        static is_callable_detail::no  check(...);

        static const bool value_args = sizeof(check<Callable>(nullptr)) == sizeof(is_callable_detail::yes);
        static const bool value_return = is_callable_detail::check_return<value_args, Callable, ReturnType, Args...>::value;
    public:
        static const bool value = value_args && value_return;
};

#endif // IS_CALLABLE_HPP

私の質問は、引数を持たず、戻り値の型 T のみを持つテンプレート化された operator() を検出する方法です

template<typename T>
T operator()()
{
  // ...
}

また

template<typename T, typename U>
auto operator()() -> decltype(std::declval<T>() + std::declval<U>())
{
  // ...
}

このような状況はめったにないことはわかっていますが、引数なしで 1 つ以上のテンプレート引数を使用してテンプレート化された operator() の存在を検出する方法はありますか?

4

2 に答える 2