从const¶meter到¶meter的无效转换似乎是无稽之谈?

时间:2016-11-17 10:37:42

标签: c++ c++11 reference const function-pointers

我只是好奇。我正在将指针传递给带签名的函数

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对象引用。

我哪里错了?

2 个答案:

答案 0 :(得分:2)

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

关于const的规则非常简单:X*可以转换为X const*X**可以转换为X const * const *,依此类推。引用相同的东西。不允许任何其他事情。

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

是否可以延长这些规则,以便它们适应像您这样的情况并保持一致?可能是这样。但他们不是。

答案 1 :(得分:1)

C ++有一组有限的情况,可以隐式添加或删除const。你遇到了一个无法完成的事情。之所以没有,可能就像&#34;描述那些安全的案件一样困难,标准作者是懒惰和保守的#34;。

作为一种解决方法,你可以这样做:

CommandLogFilter bob(
  logServer,
  parent,
  [](CommandDescriptor &descriptor) {
    return printCommandReceived(descriptor);
  }
);

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

我不想在那里明确签名,但是没有办法与模板&#34; auto&#34;不幸的是,lambdas并签署了签名。