我想在std::function
中存储和识别std::map
个对象。
要确定我想使用std::function::target
。
如果我使用std::function::target
绑定到类中的成员函数,我无法从std::bind
获取指针。
#include <functional>
#include <iostream>
using namespace std;
void normal_fun(int a)
{
std::cout << "hello\n"<<a;
}
class testclass
{
public:
int b;
void mytest(int a)
{
b = a;
}
};
uintptr_t getFuncAddress(std::function<void(int)> &f)
{
uintptr_t returnAddress = reinterpret_cast<uintptr_t>(f.target<void(*)(int)>());
return returnAddress;
}
int main()
{
testclass c;
std::function<void(int)> f1 = bind(&testclass::mytest,&c, placeholders::_1);
std::function<void(int)> f2 = normal_fun;
auto addrF1 = getFuncAddress(f1);
auto addrF2 = getFuncAddress(f2);
}
我怎样才能达到我想做的目的?
答案 0 :(得分:2)
std::function
不是函数指针。它甚至不是指针。
如果您知道std::function
中存储的类型,您可以获得指向它存储内容的指针。请注意,这里的指针不是函数指针,而是指向函数指针的指针。
如果您不知道它存储的类型,则不能。
如果您需要<
或==
或hash
(等),std::function
不会为您提供此功能。它的类型会删除()
,复制,移动,销毁,输入和回送到原始文件。
您可以使用类型擦除技术来增强std::function
这些操作;请注意,二进制操作上的类型擦除通常比类型擦除更复杂。
类型删除某些东西不应该是解决问题的第一步,但它会解决您的问题。在C ++的SO文档中有关于类型擦除的文章。这不是一个初学者。
可能以更简单的方式解决您的潜在问题。
在任何情况下,使用从target
返回的类型来订购都不是一个好主意,因为它是指向可能自动存储对象或可能是堆存储对象的指针;其中两个将在无害操作(如移动)下具有显着不同的失效规则。 SBO(小缓冲区优化)目标将与std::function
的实例一起移动,而堆分配的目标可能与std::function
在std::move
下移动的状态保持一致类似的操作。这真是一团糟。
答案 1 :(得分:1)
std::function
的要点是为符合给定签名的可调用对象提供统一的接口和类型。您期望它也提供统一的排序键,但它不会这样做。无法对std::bind
返回的函数指针和任意函数对象和可调用对象进行排序。它们是完全不同的东西,比较它们并不合理。允许您执行的所有std::function
存储并调用它们。
如果你需要一种排序机制,你必须自己创造一些东西,你就不会从std::function
获得它。
答案 2 :(得分:0)
f.target<void(*)(int)>
错误,因为bind返回的类型不是void(*)(int)
,所以目标永远不会返回非空指针。绑定不返回函数指针。它返回一些指定类型的实现对象。
可以使用decltype
获取类型。这有点不正常,但应该是正确的:
f.target<decltype(bind(
&testclass::mytest,
(testclass*)nullptr,
placeholders::_1)
)>
但我有问题,如果我有testclass或myOtherClass或其他人类,我在getFuncAddress中不知道
如果您知道包装对象的类型,则只能使用std::function::target
。如果选择的数量有限,那么您可以尝试使用每种类型获取目标,直到返回非null。对于任意未知类型,std::function::target
对您没有任何用处。
我想在std :: map
中存储和识别std :: function对象
我认为你必须使用一些无法从std::function
中提取的外部密钥。这意味着如果您希望防止重复,您还需要一种外部方法来保证从键到函数的唯一映射。
答案 3 :(得分:0)
我想在std :: map中存储和识别std :: function对象。
我假设您要识别std::function
个对象(例如,有选择地调用或删除它们)。
在这种情况下,我使用另一个密钥,例如一个简单的unsigned
。
可以使用全局函数:
typedef unsigned Key;
Key genId()
{
static Key id = 0;
return ++id;
}
现在,std::function
个对象可以与此密钥配对。 API可以授予对配对std::function
对象的访问权限,可以使用密钥完成。