Qt5:QSharedPointer<const T>::create() 时编译错误

Qt5: compile error while QSharedPointer<const T>::create()

"expected" 是 QSharedPointer::create() 不工作还是一个错误?我得到一个错误:

/usr/include/qt5/QtCore/qsharedpointer_impl.h:439:9: error: 
invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive]
new (result.data()) T(std::forward<Args>(arguments)...);

从非 const 共享指针转换和从原始 const 指针构造函数。

我为 Qt5.7.0 和 Qt5.10.0 得到了这个。

这是一个最小的例子:

#include <QSharedPointer>

struct A {};

int main(int argc, char *argv[])
{
    auto ca = QSharedPointer<const A>::create();
    return 0;
}

这是一个文件(不是最小的)示例,但有几个工作案例,2 个不工作和一个调试。注释定义用于 "not compiling" 个部分。

#include <QSharedPointer>
#include <QDebug>

#define FROM_PTR
//#define CONST_CREATE
#define FROM_RAW_PTR
#define PERFECT_FORWARD_CREATE
//#define PERFECT_FORWARD_CREATE_CONST
#define BUILTIN_CAST


class A
{
public:
    A() = default;
    A(int i) : _i{i} {}
    void foo() const { qDebug() << "const foo" << _i; }
    void foo() {  qDebug() << "foo" << ++_i; }

private:
    int _i{0};

};

using ASPtr = QSharedPointer<A>;
using ASCPtr = QSharedPointer<const A>;


int main(int argc, char *argv[])
{
    Q_UNUSED(argc)
    Q_UNUSED(argv)

#ifdef FROM_PTR
    qDebug() << "FROM_PTR";
    auto a1 = ASPtr::create();
    a1->foo();

    auto ca1 = static_cast<ASCPtr>(a1);
    ca1->foo();
    qDebug() << "\n";
#endif // FROM_PTR


#ifdef CONST_CREATE
    qDebug() << "CONST_CREATE";
    auto ca2 = ASCPtr::create();
    ca2->foo();
    qDebug() << "\n";
#endif // CONST_CREATE


#ifdef FROM_RAW_PTR
    qDebug() << "FROM_RAW_PTR";
    auto ca3 = ASCPtr(new const A);
    ca3->foo();
    qDebug() << "\n";
#endif // FROM_RAW_PTR


#ifdef PERFECT_FORWARD_CREATE
    qDebug() << "PERFECT_FORWARD_CREATE";
    auto a2 = ASPtr::create(10);
    a2->foo();
    qDebug() << "\n";
#endif //  PERFECT_FORWARD_CREATE


#ifdef PERFECT_FORWARD_CREATE_CONST
    qDebug() << "PERFECT_FORWARD_CREATE_CONST";
    auto ca4 = ASCPtr::create(20);
    ca4->foo();
    qDebug() << "\n";
#endif //  PERFECT_FORWARD_CREATE


#ifdef BUILTIN_CAST
    qDebug() << "BUILTIN_CAST";
    QSharedPointer<A> a3 = ASPtr::create();
    a3->foo();

    auto ca4 = a3.constCast<const A>();
    ca4->foo();
    qDebug() << "\n";
#endif // BUILTIN_CAST


    return 0;
}

这是一个已知的 Qt 错误 (QTBUG-49748)。虽然它在 Qt 5.6.0 中被标记为已解决,但正如评论中指出的那样,该错误仍然存​​在。

为什么会这样?

查看 class QSharedPointer qsharedpointer_impl.h 的实现。

特别是行:

new (result.data()) T(std::forward<Args>(arguments)...);

使用 result.data() 作为新表达式 放置参数。不幸的是,不能 使用 const 指针作为放置参数(有关更多详细信息,请查看 this 此处关于 SO 的问题)。

因此,除了通过官方错误跟踪器将此报告给 Qt 开发人员之外,您无能为力。

如果你不是被迫使用 Qt 的,你可以看看标准库提供的智能指针(例如 std::shared_ptr)。

更新

如 Qt 错误跟踪器中所报告,此错误已在版本 5.11 修复here 是相关提交) .基本上,他们使用 std::remove_cv 从指定的类型中删除最顶层的常量。