如何检查成员操作符(类型)

how check for member operator(type)?

本文关键字:成员 操作符 类型 检查 何检查      更新时间:2023-10-16

假设我有类型barfoo。我怎样才能构造一个模板类has_call_with_arg<>,使has_call_with_arg<bar,foo>::value当且仅当

为真?
bar b;
foo f;
b(f);

编译吗?我查看了各种相关问题(包括上面提到的)并尝试

template<typename Func, typename Arg>
class has_call_with_arg
{
  struct bad {};
  struct test : Func
  {
    template<typename C>
    bad operator()(C const&r);
  };
public:
  static const bool value = 
    !std::is_same<bad, typename std::result_of<test(Arg const&)>::type >::value;
};

,但没有工作(没有检测到正确的匹配)。怎么了?

template<typename sig, typename functor> struct is_callable;
template<typename Ret, typename... Arg, typename functor> 
struct is_callable<Ret(Arg...), functor> { // partial spec
private:
    struct no {};
public:
    template<typename U> static auto f(std::nullptr_t) -> decltype(std::declval<U>()(std::declval<Arg>()...));
    template<typename U> static no f(...);
    static const int value = std::is_convertible<decltype(f<functor>(nullptr)), Ret>::value;
};

我为我的教程创建了这个内容,它解释了这个特性的构造(首先是非可变形式)。

std::result_of<test(Arg const&)>提供了一个模板形参,该形参是一个函数类型,接受对Arg const的引用并返回test。所以它的typetest,不太有用。

注意,在写的时候,需要代码

bar b;
foo f;
b(f);

有效实际上有5个要求:barfoo都有一个可访问的默认构造函数和析构函数,b(f)是一个有效的表达式。我将只关注最后一个(这可能就是你想说的)。如果您真的想要添加其他部分,可以使用标准<type_traits>属性添加这些部分。

函数std::declval非常适合假装您拥有给定类型的对象,即使您没有。它永远不能被调用,所以它通常只在decltype表达式中使用。

有两种基本方法可以实现SFINAE技巧,基于两个地方,c++允许模板参数演绎失败,只丢弃失败的声明:

首先,尝试匹配类的部分专门化:

template<typename Func, typename Arg, typename Enable = void>
struct has_call_with_arg1 : public std::false_type {};
template<typename Func, typename Arg>
struct has_call_with_arg1<Func, Arg,
    decltype(std::declval<Func&>()(std::declval<Arg&>()))>
    : public std::true_type {};

第二,当至少一个重载是函数模板时,重载解析。(类模板的非模板成员函数在这里不起作用,因为实例化类要求每个成员声明都是有效的。)

namespace has_call_with_arg_impl {
    template<typename F, typename A>
    std::true_type test(decltype(std::declval<F&>()(std::declval<A&>()))*);
    template<typename F, typename A>
    std::false_type test(...);
}
template <typename Func, typename Arg>
struct has_call_with_arg2
    : public decltype(has_call_with_arg_impl::test<Func,Arg>(nullptr)) {};

演示:http://ideone.com/KgRI8y