从常量 &参数到 &参数的无效转换似乎是无稽之谈?



我只是好奇。我正在传递指针到函数签名

void printCommandReceived(const CommandDescriptor &descriptor)

作为签名

的构造函数的第三个形参
CommandLogFilter::CommandLogFilter(QSharedPointer<LogServer> logServer, QObject *parent,
                      void (*preprocessValidCommand)(CommandDescriptor &descriptor))

和从g++编译器得到错误:

error: invalid conversion from ‘void (*)(const CommandDescriptor&)’ to ‘void (*)(CommandDescriptor&)’ [-fpermissive]

在我的理解中,对非const对象的引用应该可用作引用const对象形参的实参。因此,接受非const对象引用的指向函数的指针类型形参应该比接受甚至接受const对象引用的指向函数的指针类型形参更令人满意(并进行隐式转换)。

我错在哪里?

void (*)(const CommandDescriptor&)void (*)(CommandDescriptor&)是两种完全不同、不相关的类型。

关于const有非常简单的规则:X*可以转换为X const*, X**可以转换为X const * const *,等等。参考文献也是一样。

注意,规则不允许在类型的任何位置任意添加或删除const,例如,X**不能转换为X const **。对于函数参数的位置也是如此:您不能在那里添加或删除const以获得兼容的类型。

这些规则是否可以扩展,以适应像您这样的情况并保持一致?可能如此。

c++在有限的情况下可以隐式地添加或删除const。你遇到了一个无法做到的问题。原因可能很简单,因为"描述那些安全的情况会很困难,标准的编写者又懒又保守"。

作为一种变通方法,你可以这样做:
CommandLogFilter bob(
  logServer,
  parent,
  [](CommandDescriptor &descriptor) {
    return printCommandReceived(descriptor);
  }
);

作为无状态lambda可以隐式转换为指向与其签名匹配的函数的指针。

我不喜欢在那里显式签名,但是没有办法对模板"auto" lambdas做类似的事情,不幸的是,签名是推导出来的。

最新更新