我只是好奇。我正在传递指针到函数签名
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做类似的事情,不幸的是,签名是推导出来的。