QList::emplace_back()
-
I'm finally moving our projects to the Qt6 space. Sadly this means my beloved QVector is no longer with us, only in name.
I stumbled on the following (simplified example):
#include <QCoreApplication> #include <QList> #include <QDebug> class TestClassConst{ public: TestClassConst(const int &value) : m_value(value){ qDebug() << "Constructor"; } TestClassConst(TestClassConst && other): m_value{other.m_value} { qDebug() << "Move Constructor"; } TestClassConst(const TestClassConst & other): m_value{other.m_value} { qDebug() << "Copy Constructor"; } // QList::emplace_back requieres this! delete is not possible // TestClassConst & operator=(const TestClassConst & other) = delete; TestClassConst & operator=(const TestClassConst & other) { qDebug() << "Copy Assignment"; return *this; } int value() const {return m_value;} private: const int m_value{0}; }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qDebug() << "std"; //the truth std::vector<TestClassConst> vectorStd; vectorStd.emplace_back(42); qDebug() << "Qt"; //the lie QList<TestClassConst> list; list.emplace_back(41); qDebug() << list.first().value(); }
the console output:
std Constructor Qt Constructor Move Constructor 41
however, the QList section will not compile if I set the Copy Assignment operator to delete. Even though QList::emplace_back doesn't even seem to use it. I'm super confused and I would rather not have an empty non functional copy assignment operator in my classes if I can avoid it.
Any help or enlightenment appreciated!
-
If you really want to enforce immutability (no copy assignment), you can:
Use std::vector<TestClassConst> instead of QList<TestClassConst>.
If you must use QList, consider allowing move assignment but still deleting copy assignment:TestClassConst & operator=(const TestClassConst & other) = delete;
TestClassConst & operator=(TestClassConst && other) noexcept = default;This will prevent copies but allow moves, making it compatible with QList.
-
QList, despite its improvements in Qt 6, still has legacy behavior that requires an assignable type in some cases. If you're working with immutable or non-copyable types, std::vector is usually the better choice.
-
@Shankarlinga-M thanks for your input!
The use case is basically a container class, with - almost only -, readOnly access from outside.
It will be read from user provided files during runtime and exist until a new set is read or the program is closed.
The objects are created and "stored" in a List/Vector to be passed to where they are need to be read.
So the list should per design choice be immutable. And I would like to enforce it.The default move assignment operator is deleted due to const members, so thats out too.
Looks so far, as if the cleanest way would be using std::vector. Not sure how much refactor/extra work that will be :(