Qt5中QSharedPointer<const T>::create()编译错误问题咨询
Hey there, let's sort out this annoying compile error with QSharedPointer<const T>::create() in those specific Qt versions. Here's everything you need to know:
The Problem
When you try to call QSharedPointer<const T>::create() in Qt 5.7.0 or 5.10.0, you'll hit this compile error:
/usr/include/qt5/QtCore/qsharedpointer_impl.h:439:9: error: invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive] new (result.data()) T(std::forward
(arguments)...);
But here's the kicker—you can still create a QSharedPointer<const T> just fine by converting from a non-const shared pointer, or constructing directly from a raw const pointer.
Why This Happens
This is a known Qt implementation bug in those versions. When instantiating QSharedPointer<const T>, the internal memory allocation returns a const void* pointer, but the placement new operation requires a non-const void*. The type mismatch throws the compiler off. The non-const QSharedPointer<T>::create() works because it returns a non-const pointer that plays nicely with placement new.
Working Fixes
You have a few solid workarounds to get around this bug:
1. Convert from a Non-Const QSharedPointer
First create a regular QSharedPointer<T>, then cast or assign it to QSharedPointer<const T>—Qt handles the conversion implicitly:
auto nonConstPtr = QSharedPointer<A>::create(); QSharedPointer<const A> constPtr = nonConstPtr; // Or use static_cast for explicit type conversion QSharedPointer<const A> constPtr = static_cast<QSharedPointer<const A>>(nonConstPtr);
2. Construct from a Raw Const Pointer
Skip the create() method entirely and build the shared pointer from a raw const pointer (supports constructor arguments too):
// Default constructor QSharedPointer<const A> constPtr(new const A); // With constructor parameters QSharedPointer<const A> constPtr(new const A(20));
3. Use QSharedPointer's Built-in constCast
Leverage the constCast method provided by QSharedPointer to switch types safely:
auto nonConstPtr = QSharedPointer<A>::create(); auto constPtr = nonConstPtr.constCast<const A>();
Full Test Code
Here's a complete test script showing all working scenarios (the commented sections are the ones that fail to compile):
#include <QSharedPointer> #include <QDebug> #define FROM_PTR //#define CONST_CREATE // Uncomment this to trigger the compile error #define FROM_RAW_PTR #define PERFECT_FORWARD_CREATE //#define PERFECT_FORWARD_CREATE_CONST // Uncomment this to trigger the compile error #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(); // Example with constructor arguments auto ca3WithArg = ASCPtr(new const A(15)); ca3WithArg->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_CONST #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; }
Bonus Note
This bug was fixed in later Qt versions (starting around Qt 5.12), so if you can upgrade your Qt version, that's the most permanent solution.
内容的提问来源于stack exchange,提问作者BPiek

