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 从指定的类型中删除最顶层的常量。
"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 从指定的类型中删除最顶层的常量。