如何检查类型是否存在无参数运算符()

Gri*_*zly 7 c++ templates metaprogramming c++11

我正在尝试检查仿函数是否与给定的一组参数类型和给定的返回类型兼容(也就是说,给定的参数类型可以被隐含地转换为实际的参数类型,反之亦然的是返回类型).目前我使用以下代码:

    template<typename T, typename R, template<typename U, typename V> class Comparer>
    struct check_type
    { enum {value = Comparer<T, R>::value}; };

    template<typename T, typename Return, typename... Args>
    struct is_functor_compatible
    {
        struct base: public T
        {
            using T::operator();
            std::false_type operator()(...)const;
        };
        enum {value = check_type<decltype(std::declval<base>()(std::declval<Args>()...)), Return, std::is_convertible>::value};
    };
Run Code Online (Sandbox Code Playgroud)

check_type<T, V, Comparer> 这在大多数情况下非常struct foo{ int operator()() const;};好用,但是当我测试无参数仿函数时,它无法编译,因为在这种情况下,两个operator()基数显然是暧昧的,导致类似这样的事情:

error: call of '(is_functor_compatible<foo, void>::base) ()' is ambiguous
note: candidates are:
note: std::false_type is_functor_compatible<T, Return, Args>::base::operator()(...) const [with T = foo, Return = void, Args = {}, std::false_type = std::integral_constant<bool, false>]
note: int foo::operator()() const
Run Code Online (Sandbox Code Playgroud)

因此,我需要一种不同的方法来检查无参数仿函数.我尝试is_functor_compatible对一个空的parameterpack 进行部分特化,在那里我检查类型是否&T::operator()是无参数的成员函数,它的工作方式或多或少.然而,当测试的仿函数有几个时,这种方法显然会失败operator().

因此,我的问题是,是否有更好的方法来测试无参数的存在operator()以及如何进行.

R. *_*des 8

当我想测试给定表达式是否对某个类型有效时,我使用类似于这个的结构:

template <typename T>
struct is_callable_without_parameters {
private:
    template <typename T1>
    static decltype(std::declval<T1>()(), void(), 0) test(int);
    template <typename>
    static void test(...);
public:
    enum { value = !std::is_void<decltype(test<T>(0))>::value };
};
Run Code Online (Sandbox Code Playgroud)

  • @Grizzly第一部分是针对我们正在寻找的表达式的SFINAE.最后的`0`是一个`int`返回类型,因为如果`std :: declval <T1>()()`部分有'void`作为返回类型,你将无法区分过载.中间的`void()`是为了防止由于重载的逗号运算符引起讨厌的事情. (3认同)