c++ - 编译器更新后“const_cast 的使用无效”,为什么?

标签 c++ callback

从 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/

相关文章:

c++ - 寻找 C++ 的 MSHTML 包装器

c++ - 无法编译mysql源码

c++ - 从C++中的txt文件中读取字符

ruby-on-rails - 如何异步处理 Rails 观察者和回调(在不同的线程中)?

events - 主干 : how the trigger function works

c++ - 通过迭代器访问 qlist 元素的段错误

c++ - 谁能解释一下这个 C++ 程序。结果很奇怪 :(

c++ - 在 c++ std::function 上下文中无效使用 void 表达式

python - 在 tk.Entry textvariable 上调用 tk.StringVar.set() 会导致 validate ="focusout"停止被调用

javascript - Angular 服务在回调函数中部分可用