如何确定一个类型是否可调用只有const引用? [英] How do I determine if a type is callable with only const references?

查看:119
本文介绍了如何确定一个类型是否可调用只有const引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要写一个定义 value 为<$ c的C ++元函数 is_callable $ c> true ,当且仅当类型F具有形式的函数调用操作符SomeReturnType operator()(const Arg&) 。例如,在下列情况下

I want to write a C++ metafunction is_callable<F, Arg> that defines value to be true, if and only if the type F has the function call operator of the form SomeReturnType operator()(const Arg &). For example, in the following case

struct foo {
  void operator(const int &) {}
};

我想要 is_callable< foo,int&> false is_callable< foo,const int&> true 。这是我到目前为止:

I want is_callable<foo, int &> to be false and is_callable<foo, const int &> to be true. This is what I have so far :

#include <memory>
#include <iostream>

template<typename F, typename Arg>
struct is_callable {
private:

  template<typename>
  static char (&test(...))[2];

  template<unsigned>
  struct helper {
    typedef void *type;
  };

  template<typename UVisitor>
  static char test(
               typename helper<
                 sizeof(std::declval<UVisitor>()(std::declval<Arg>()), 0)
                 >::type
               );
public:
  static const bool value = (sizeof(test<F>(0)) == sizeof(char));
};

struct foo {
  void operator()(const int &) {}
};

using namespace std;

int main(void)
{
  cout << is_callable<foo, int &>::value << "\n";
  cout << is_callable<foo, const int &>::value << "\n";

  return 0;
}

打印 1 1 ,但我想要 0 1 code> foo 只定义 void operator()(const int&)

This prints 1 and 1, but I want 0 and 1 because foo only defines void operator()(const int &).

推荐答案

经过几个小时的游戏和一些在C ++中的严肃讨论聊天室,我们终于得到了一个版本,可用于可能重载或继承的函数 operator()以及基于@ KerrekSB和@ BenVoigt的版本的函数指针。

After hours of playing around and some serious discussions in the C++ chat room, we finally got a version that works for functors with possibly overloaded or inherited operator() and for function pointers, based on @KerrekSB's and @BenVoigt's versions.

#include <utility>
#include <type_traits>

template <typename F, typename... Args>
class Callable{
  static int tester[1];
  typedef char yes;
  typedef yes (&no)[2];

  template <typename G, typename... Brgs, typename C>
  static typename std::enable_if<!std::is_same<G,C>::value, char>::type
      sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (C::*pfn)(Brgs...));

  template <typename G, typename... Brgs, typename C>
  static typename std::enable_if<!std::is_same<G,C>::value, char>::type
      sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (C::*pfn)(Brgs...) const);

  template <typename G, typename... Brgs>
  static char sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (G::*pfn)(Brgs...));

  template <typename G, typename... Brgs>
  static char sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (G::*pfn)(Brgs...) const);

  template <typename G, typename... Brgs>
  static yes test(int (&a)[sizeof(sfinae<G,Brgs...>(&G::operator()))]);

  template <typename G, typename... Brgs>
  static no test(...);

public:
  static bool const value = sizeof(test<F, Args...>(tester)) == sizeof(yes);
};

template<class R, class... Args>
struct Helper{ R operator()(Args...); };

template<typename R, typename... FArgs, typename... Args>
class Callable<R(*)(FArgs...), Args...>
  : public Callable<Helper<R, FArgs...>, Args...>{};

Ideone上的实例。注意,两个失败的测试是重载的 operator()测试。这是一个带有可变参数模板的GCC错误,已在GCC 4.7中修复。 Clang 3.1还报告所有测试通过

Live example on Ideone. Note that the two failing tests are overloaded operator() tests. This is a GCC bug with variadic templates, already fixed in GCC 4.7. Clang 3.1 also reports all tests as passed.

如果你想要 operator / code>使用默认参数失败,有一种可能的方法,但是一些其他测试将开始失败在那一点,我发现它太麻烦,尝试和纠正。

If you want operator() with default arguments to fail, there is a possible way to do that, however some other tests will start failing at that point and I found it as too much hassle to try and correct that.

编辑:由于@Johannes在注释中正确注释,我们在这里有一点不一致,即

As @Johannes correctly notes in the comment, we got a little inconsistency in here, namely that functors which define a conversion to function pointer will not be detected as "callable". This is, imho, pretty non-trivial to fix, as such I won't bother with it (for now). If you absolutely need this trait, well, leave a comment and I'll see what I can do.

所有这一切已经说过, ,这个特征的想法是愚蠢的。为什么你有这样的确切要求?为什么标准 is_callable 不够用?

Now that all this has been said, IMHO, the idea for this trait is stupid. Why whould you have such exact requirements? Why would the standard is_callable not suffice?

(是的,我认为想法很愚蠢。是的,很有趣,很不错,不,我不疯了,至少这是我相信...)

(Yes, I think the idea is stupid. Yes, I still went and built this. Yes, it was fun, very much so. No, I'm not insane. Atleast that's what I believe...)

这篇关于如何确定一个类型是否可调用只有const引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆