有没有办法创建由 `std::function<>` 包装的函数的哈希值?

2024-03-12

我有一个 C++ 函数,需要一个std::function作为输入参数。
具体来说,一个std::function<void (const Message&, Error)>.

在我的用例中,调用者可以绑定std::function到自由函数或成员函数。

(我没有经验std::bind or std::function,所以我发现值得注意的是,相同的对象类型,std::function<void (const Message&, Error)>,可以绑定到自由函数和成员函数——后者通过使用std::bind。我发现它很有趣,因为它似乎抽象了函数指针和成员函数指针的区别 https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types(至少给我这样的印象))

对于我的调试需要,记录一个哈希值是有用的,它是与std::function输入参数。
在这里,我很快意识到我无法逃避自由函数指针和成员函数指针之间的根本区别。
我可以获得底层void (*)(const Message&, Error)自由函数指针使用std::function::target<void (*)(const Message&, Error)>(),它作为一个独特的哈希满足我的需求。
但这不起作用,如果std::function<void (const Message&, Error)>绑定到成员函数。
在我的脑海里,我推断如果std::function<void (const Message&, Error)>被绑定到class Foo成员函数,那么std::function::target<void (Foo::*)(const Message&, Error)>()会返回指向成员函数指针的指针——但情况似乎并非如此。

这导致我的问题:有没有什么方法可以从 a 中获取唯一的哈希值std::function实例,无论它绑定到自由函数还是成员函数?

#include <functional>
#include <iostream>

using namespace std;

struct Message {
  int i_;
};

struct Error {
  char c_;
};

class Foo {
public:
  void print(const Message& m, Error e) {
    cout << "member func: " << m.i_ << " " << e.c_ << endl;
  }
};

void print(const Message& m, Error e) {
  cout << "free func: " << m.i_ << " " << e.c_ << endl;
};

void doWork(function<void (const Message&, Error)> f) {
  // I can invoke f regardless of whether it's been bound to a free function or
  // a member function...
  {
    Message m{42};
    Error e{'x'};

    f(m, e);
  }

  // ...but since I don't know whether f is bound to a free function or a member
  // function, I can't use std::function::target<>() to generically get a
  // function pointer, whose (void*) value would have served my need for a
  // hash...
  {
    typedef void (*Fptr)(const Message&, Error);
    typedef void (Foo::*Mfptr)(const Message&, Error);

    Fptr* fptr = f.target<Fptr>();
    Mfptr* mfptr = nullptr;

    cout << "free func target: " << (void*)fptr << endl;

    if (fptr) {
      cout << "free func hash: " << (void*)*fptr << endl;
    }
    else {
      // ...moreover, when f is bound to a Foo member function (using
      // std::bind), std::function::target<>() doesn't return a Foo member
      // function pointer either...I can't reason why not.
      // (this also isn't scalable because in future, f may be bound to a 
      // class Bar or class Baz member function)
      mfptr = f.target<Mfptr>();
      cout << "not a free function; checking for a Foo member function" << endl;
      cout << "member func target: " << (void*)mfptr << endl;

      if (mfptr) {
        cout << "member func hash: " << (void*)*mfptr << endl;
      }
    }
  }
}

int main()
{
  {
    function<void (const Message&, Error)> f = print;

    doWork(f);
  }

  cout << "---" << endl;

  {
    Foo foo;
    function<void (const Message&, Error)> f = bind(&Foo::print,
                                                    &foo,
                                                    placeholders::_1,
                                                    placeholders::_2);

    doWork(f);
  }

  return 0;
}

编译及输出:

$ g++ --version && g++ -g ./main.cpp && ./a.out
g++ (Debian 8.3.0-6) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

free func: 42 x
free func target: 0x7ffda4547bf0
free func hash: 0x55db499c51e5
---
member func: 42 x
free func target: 0
not a free function; checking for a Foo member function
member func target: 0

以下代码:

#include <functional>
#include <iostream>
#include <vector>
#include <string>
#include <cstdint>

int f(int a) { return -a; }
int f2(int a) { return a; }

int main() {
    std::vector<std::function<int(int)>> fn{
        f,
        f,
        f2,
        f2,
        [](int a) {return -a;},
        [](int a) {return -a;},
        [](int a) {return -a;},
    };

    for (auto&& a : fn) {
        const auto t = a.target<int(*)(int)>();
        const auto hash = t ?
            (size_t)(uintptr_t)(void*)*t :
            a.target_type().hash_code();
        std::cout << hash << '\n';
    }
}

由两个 f 函数、两个 f2 函数和 3 个 lambda 函数组成的初始化向量。因此,我们期待两个相同的哈希值,两个相同的哈希值,并且每个 lambda 都是一个新类型 - 3 个不同的哈希值。代码输出:

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

有没有办法创建由 `std::function<>` 包装的函数的哈希值? 的相关文章

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • 改变字典的哈希函数

    按照此question https stackoverflow com questions 37100390 towards understanding dictionaries 我们知道两个不同的字典 dict 1 and dict 2例
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置

随机推荐