如何确定类型是否可以仅使用 const 引用进行调用?

2024-03-06

我想写一个 C++ 元函数is_callable<F, Arg>定义了value to be true,当且仅当类型 F 具有以下形式的函数调用运算符SomeReturnType operator()(const Arg &)。例如,在以下情况下

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

I want is_callable<foo, int &> to be false and is_callable<foo, const int &> to be true。这是我到目前为止所拥有的:

#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 and 1, 但我想要0 and 1因为foo只定义void operator()(const int &).


经过几个小时的玩耍和一些C++聊天室里认真讨论 https://chat.stackoverflow.com/transcript/message/2392901#2392901,我们终于得到了一个适用于可能重载或继承的函子的版本operator()对于函数指针,基于@KerrekSB 和@BenVoigt 的版本。

#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 上的实例 http://ideone.com/Q20BZ。请注意,两个失败的测试都是超载的operator()测试。这是一个带有可变参数模板的 GCC 错误,已在 GCC 4.7 中修复。 Clang 3.1 还将所有测试报告为passed.

如果你想operator()如果默认参数失败,有一种可能的方法可以做到这一点,但是其他一些测试将在那时开始失败,我发现尝试纠正它太麻烦了。

Edit:正如@Johannes 在评论中正确指出的那样,我们在这里遇到了一些不一致的地方,即定义函数指针转换的函子 https://stackoverflow.com/q/8873048/500104不会被检测为“可调用”。恕我直言,修复这个问题并不简单,因此我不会为此烦恼(暂时)。如果您绝对需要这个特性,那么请发表评论,我会看看我能做什么。


既然这一切都已经说了,IMHO,这个特质的想法是愚蠢的。为什么你会有这样的exact要求?为什么要制定标准is_callable还不够吗?

(是的,我认为这个想法很愚蠢。是的,我仍然去建造了这个。是的,这很有趣,非常有趣。不,我没有疯。至少我是这么认为的......)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何确定类型是否可以仅使用 const 引用进行调用? 的相关文章

随机推荐

  • Java:在for循环init中初始化多个变量?

    我想要两个不同类型的循环变量 有什么办法可以让这个工作吗 Override public T get int index throws IndexOutOfBoundsException syntax error on first int
  • 放大 AMCharts 时丢失 Timeserie

    当我放大图表时 serie2 消失了 如果我通过从右侧选择光标进行缩放 但是从左侧缩放工作正常 无论如何 我期待看到 2 系列 但似乎有时不是 See my 截屏 https i stack imgur com MXsX1 png 知道为什
  • 在opencv c++中绘制旋转矩形

    我想用c 在opencv中绘制一个旋转的矩形 我用 rectangle 函数如下 rectangle RGBsrc vertices 0 vertices 2 Scalar 0 0 0 CV FILLED 8 0 但是这个函数画了一个0角的
  • 从 C# 安装项目运行另一个程序

    我已经用 C 创建了一个设置和部署项目 现在我有另一个 Windows 更新 exe 我想在安装我的项目之前成功运行和安装它 我已将 exe 与我的项目打包在一起 我之前如何运行该exe 您想要将自定义操作添加到运行可执行文件的安装项目 本
  • 根据等于 x.x.x.x/x 的 IP 字符串计算 IP 范围

    给定 IP 字符串 我如何计算 IP 范围x x x x x最常见的情况可能是198 162 1 1 24但可以是任何东西 任何法律允许的东西 我要拿198 162 1 1 24并将其转换为 198 162 1 1 198 162 1 12
  • 音频 - 快进 30 秒

    我有一个音频播放器 可以播放从 Core Date 检索到的音频 播放和暂停工作正常 我正在尝试实现 向前跳转 30 秒 按钮 并寻求有关如何实现该操作的任何指示 我的 播放 暂停 按钮的代码 IBAction func playPress
  • Python Selenium Webdriver - 动态更改下载目录

    为了在定义 selenium webdriver 之前显式定义下载目录 我们使用以下代码 chromeOptions webdriver ChromeOptions prefs download default directory C da
  • 使用 Mayavi 制作 3D 图表,并使用 Matplotlib 风格的轴

    我一直在用 Mayavi 进行 3D 绘图 我可以绘制我想要的散点图 但似乎无法让轴看起来正确 我发现了以下内容上一个问题 https stackoverflow com questions 4739360 any easy way to
  • JOOQ 嵌套条件

    嗨 我想弄清楚如何在 jooq 中写这样的东西 select from table where a query or b query or a query and e query or g query or z query 我不知道如何在
  • 将相等的矩形拟合成更大的矩形

    我有一个大矩形dimensions L W and n smaller rectangles每个都有相同的尺寸l w 每个小矩形都有相同的dimensions 我的目标是适合所有人n of smaller将矩形合并到大矩形中 同时尽可能最有
  • Rails 5.2 中范围内的连接与 Rails 5.1 有何不同?

    将 Rails 从 5 1 升级到 5 2 后 我开始收到以下错误 NoMethodError undefined method expr for nil NilClass from gems path activerecord 5 2 0
  • 该捆绑包无效。 Apple 目前不接受使用此版本的 SDK 4.2 构建的应用程序 [已关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 亲爱的关心
  • Hibernate:映射3个表

    我正在尝试使用 Hibernate 映射一些现有表 这很简单 我们有具有多种语言名称的类别 DDL如下 create table language id integer not null auto increment code varcha
  • 有没有办法在logback中为单个日志文件定义多个滚动策略?

    我正在尝试设置一个 logback 配置 该配置创建一个解压缩的日志文件作为第一卷 然后从那时起将压缩文件写入不同的目录 我相信最好的方法是在单个附加程序中创建多个rollingPolicy 元素 谁能指导我一个有人成功做到这一点的例子
  • 向 Azure IoT 中心分区发送消息

    有谁知道是否有一个库允许您使用 Azure 将消息发送到 IoT 中心上的特定分区 我以前能够使用 azuresblite 库实现这一点 不幸的是我无法使用它 https github com ppatierno azuresblite h
  • 声明堆栈变量而不指定名称并获取指针

    众所周知 定义一个堆变量new获取指针而不指定名称 Var p new Var name 1 但我必须清除指向的变量p with delete p稍后在节目中 我想声明一个堆栈变量 以便在函数退出后自动清除它 但我只想获取指针 以及以下内容
  • 弹出窗口中的动态 iframe

    我试图通过下面的 href 链接实现两件事 首先 我想启动一个弹出窗口 完毕 接下来 我希望弹出窗口显示 iframe 这也很容易完成until我意识到我需要将 href 链接文本作为 iframe src 中的参数传递 例如 iframe
  • 如何绘制 CSV 数据

    我有一个 python 代码 其中使用 pandas 读取 csv 文件并将日期和时间存储在一列中Datetime 现在我想在 y 轴上绘制传感器值 在 x 轴上绘制日期时间 我怎样才能做到这一点 我的代码如下 import pandas
  • 从 DialogFragment 调用 registerReceiver

    EDIT 我添加了这一行 getActivity registerReceiver new BroadcastReceiver new IntentFilter SENT 但现在出现运行时错误 错误内容如下 09 03 04 12 41 8
  • 如何确定类型是否可以仅使用 const 引用进行调用?

    我想写一个 C 元函数is callable