从 Ubuntu 17.04 升级到 17.10 后,我有一段代码无法再编译。我的编译器 g++ 已从 6.3.0 更新到 7.2.0。
我没有接触过代码,但我不明白为什么它不再编译。
void MessageBus::removeListener(std::function<Message*(Message*)> listener)
{
// For every registered message listener
for(auto it = listeners.begin(); listeners.size() && it != listeners.end(); it++) {
auto registeredListener = it->target<Message*(Message*)>();
// If the current std::function::target is the same as the one that the caller wants to remove
if(registeredListener == listener.target<Message*(Message*)>())
// Remove it from the listener list
listeners.erase(it);
}
}
我得到的错误如下:
In file included from /usr/include/c++/7/functional:58:0,
from MessageBus.h:6,
from MessageBus.cpp:1:
/usr/include/c++/7/bits/std_function.h: In instantiation of ‘_Functor* std::function<_Res(_ArgTypes ...)>::target() [with _Functor = MyNamespace::Message*(MyNamespace::Message*); _Res = MyNamespace::Message*; _ArgTypes = {MyNamespace::Message*}]’:
MessageBus.cpp:25:70: required from here
/usr/include/c++/7/bits/std_function.h:733:9: error: invalid use of const_cast with type ‘MyNamespace::Message* (*)(MyNamespace::Message*)’, which is a pointer or reference to a function type
return const_cast<_Functor*>(__func);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MessageBus.cpp:25 是行 auto registeredListener = it->target<Message*(Message*)>();
std::function::target 始终是如下所示的方法 Message* Foo::bar(Message*)
以防万一。
为什么不再编译?
最佳答案
似乎如果 std::function 包含实际函数,则 target() 函数的类型参数必须是函数指针而不是函数签名。
在你的情况下,这应该编译:
it->target<Message*(*)(Message*)>();
但是,我认为类型参数必须与 std::function 包含的实际类型相匹配。因此,如果 std::function 包含由 std::bind() 或 lambda 创建的仿函数,并且您使用类型参数作为函数指针调用 target(),它将返回零。
演示:
#include <iostream>
#include <functional>
class Message;
struct A
{
Message* f(Message* m) { return m; };
};
Message* f(Message* m) { return m; };
int main()
{
using namespace std::placeholders;
A a;
auto functor = std::bind(&A::f, a, _1);
std::function<Message*(Message*)> functorF(functor);
std::function<Message*(Message*)> functionF(&f);
auto t1 = functionF.target<Message*(*)(Message*)>();
std::cout << "Function as function pointer: " << (t1 != 0) << std::endl;
auto t2 = functorF.target<Message*(*)(Message*)>();
std::cout << "Functor as function pointer: " << (t2 != 0) << std::endl;
auto t3 = functorF.target<decltype(functor)>();
std::cout << "Functor as functor: " << (t3!= 0) << std::endl;
}
结果:
Function as function pointer: 1
Functor as function pointer: 0
Functor as functor: 1
我怀疑在 GCC 6.3.0 中您对 target() 的调用总是返回零,因此 Eljay 指出的无效迭代器的潜在错误从未发生过。
关于c++ - 编译器更新后“const_cast 的使用无效”,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47369265/