1

Is it "expected" for QSharedPointer::create() not to work or is it a bug? I get an 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<Args>(arguments)...);

casting from nonconst shared pointer and constructor from raw const pointer work.

I got this for Qt5.7.0 and Qt5.10.0.

Here is a minimal example:

#include <QSharedPointer>

struct A {};

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

Here is one file (not minimal) example but with few working cases, 2 not working and a debug. Commented defines are for "not compiling" parts.

#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;
}
BPiek
  • 174
  • 11

1 Answers1

3

That is a known Qt bug (QTBUG-49748). Although it is marked as resolved in Qt 5.6.0, the bug is still present as pointed out in the comments.

Why is this happening?

Look at the implmentation of the class QSharedPointer qsharedpointer_impl.h.

In particular the line:

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

uses the result.data() as the new expression placement params. Unfortunately, one can not use a const pointer as a placement param (have a look at this question here on SO for more details).

Hence, there's not much you can do except reporting this to Qt developers via the official bug tracker.

You may have a look at the smart pointers provided by the standard library (e.g. std::shared_ptr) if you are not forced to use Qt ones.

UPDATE

As reported in Qt bug tracker, this bug was fixed in version 5.11 (here is the related commit). Basically, they used std::remove_cv to remove the topmost const from the type specified.

Sergio Monteleone
  • 2,776
  • 9
  • 21
  • Thanks. I created new [issue](https://bugreports.qt.io/browse/QTBUG-68300). – BPiek May 16 '18 at 08:38
  • I'll use `QSharedPointer(new T(...))`. It won't probably do anything with memory segmentation though. – BPiek May 16 '18 at 09:24