STL or Qt containers?
I started by using std::(w)string
and the STL containers exclusively and converting to/from the Qt equivalents, but I have already switched to QString
and I find that I'm using Qt's containers more and more.
When it comes to strings, QString
offers much more complete functionality compared to std::basic_string
and it is
completely Unicode aware. It also offers an efficient COW implementation, which I've come to rely on heavily.
Qt's containers:
- offer the same COW implementation as in
QString
, which is extremely useful when it comes to using Qt'sforeach
macro
(which does a copy) and when using meta-types or signals and slots. - can use STL-style iterators or Java-style iterators
- are streamable with
QDataStream
- are used extensively in Qt's API
- have a stable implementation across operating systems. A STL implementation must obey the C++ standard, but
is otherwise free to do as it pleases (see thestd::string
COW controversy). Some STL implementations are especially
bad. - provide hashes, which are not available unless you use TR1
The QTL has a different philosophy from the STL, which is well summarized by J. Blanchette: "Whereas STL's containers are optimized for raw speed, Qt's container classes have been carefully designed to provide convenience, minimal memory usage, and minimal code expansion."
The above link provides more details about the implementation of the QTL and what optimizations are used.
Generic Search Algorithms for Qt container classes
STL algorithms defined in algorithm
header can be used with Qt containers. If Qt lacks an equivalent algorithm there is no reason to avoid using the STL algorithm. If Qt is built with STL support it should work by default.
#include <algorithm> // std::find_if
#include <QApplication>
#include <QVector>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QVector<int> c{ 2,3,4,6,6,15 };
if (std::find_if(c.begin(), c.end(), [](const int& value) { return value % 5 == 0; }) != c.end()) {
...
}
return app.exec();
}
How to use STL algorithms in Qt?
This function locates in std namespace, so just write:
#include <QApplication>
#include <algorithm>
#include <QVector>
using namespace std;//new line!
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QVector<int>vec{9,6,10,5,7};
sort(vec.begin(),vec.end());
return a.exec();
}
Or write std::sort
every time:
#include <QApplication>
#include <algorithm>
#include <QVector>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QVector<int>vec{9,6,10,5,7};
std::sort(vec.begin(),vec.end());
return a.exec();
}
Using STL algorithms with Qt containers
std::copy_if
increments the output iterator when copying elements. You passed it searchResult.begin()
which is equally an end()
iterator since searchResult
is an empty container. And increment(ing) an iterator passed the end()
iterator invokes Undefined Behavior.
since QList<T>
supports a push_back(T)
member function, you should use std::back_inserter
to create a std::back_insert_iterator
that will be doing push back's to searchResult
std::copy_if(model->getStudentEntryList().begin(),
model->getStudentEntryList().end(),
std::back_inserter(searchResult),
condition);
How to fill STL containers by means of generate_n with index increment
You can move the index into the lambda capture and make the lambda mutable like this (requires C++14):
std::generate_n(std::back_inserter(lst), N,
[&func, idx = -1] () mutable {idx++; return func(idx);});
Now you can omit the line int idx = -1;
. There might be a better solution though, as sacrificing the default const qualification of the closure just to move an integer declaration from the surrounding scope into the capture isn't perfect. Still though, the scope of idx
has been reduced, and if I understand your question correctly, this was the goal.
Why use QVector(Qt) instead of std::vector
This article loooks good. It compares Qt Template Library with Standard Template Library:
- QTL vs STL
Hope, you'll find it interesting seeing all the differences listed there in the article.
EDIT:
Here is what I find interesting:
My opinion is that the biggest
advantage of the QTL is that it has
the same implementation (including
binary compatibility) on all OSes
supported by Qt. Some STL
implementations might be below par
when it comes to performance or they
might be missing functionality. Some
platforms don’t even have an STL! On
the other hand, the STL is more
customizable and is available in its
entirety in header files… Like I said,
there is no clear winner.
Like he said, no clear winner. But still reading the article makes lots of things clear. Its better to know the difference than going for one, without knowing the other.
Is there still a need to provide default constructors to use STL containers?
This quote is from the C++ Programming Language, Special edition , 2005 by Bjarne Stroustrup in section 16.3.4:
If a type does not have a default constructor, it is not possible to create a vector with elements of that type, without explicitly providing the value of each element.
So it was indeed a standard requirement. It was also required that (section 17.1.4) :
To be an element of a container, an object must be of a type that allows the container implementation to copy it. The container may copy it using a copy constructor or an assignment; in either case the result of the copy must be an equivalent object.
So yes, there were "official" constructor requirementsand the library implementation were supposed to be interchangeable and not add other requirements. (Already in the very first proposal for STL in 1995, the authors tried as much as possible to clearly indicate specifications and narrow down the implementation dependent flexibility.)
You therefore had to provide a default constructor in the case where you declared other constructors:
If a user has declared a default constructor, that one will be used; otherwise, the compiler will try to generate one if needed and if the user hasn't declared other constructors.
Nowadays, this requirement is relaxed. Since C++11:
The requirements that are imposed on the elements depend on the actual operations performed on the container.
So you can define a vector for a class without default constructor, if it doesn't make sense. This for example perfectly works (online demo):
class MyClass {
public:
MyClass(int x) {}
};
int main() {
vector<MyClass> v;
MyClass test{1};
v.push_back(test);
}
But it works only as long as you don't use any operation that would need the default constructor. For instance v.resize(6);
would fail to compile.
C++ STL: Why allocators don't increase memory footprint of containers?
Your allocator is not being used.
By default, std::set
receives std::allocator<int>
, but it needs to allocate some kind of nodes, not int
s. It uses std::allocator_traits::rebind
to get a different allocator for its internal node type.
Pre-C++20 std::allocator
has a rebind
member type, which you inherit, and which std::allocator_traits::rebind
finds. That rebind
points to std::allocator
, so that's what you get.
Starting from C++20, there's no rebind
in std::allocator
, so std::allocator_traits::rebind
falls back to directly modifying the first template parameter of your allocator, and since it's not a template, you get a compilation error.
A possible solution is to make your allocator a template, and to provide your own rebind
(which can be malformed, then the template parameter will be replaced automatically):
template <typename T>
struct MyAllocator : public std::allocator<T>
{
char dummy[1024];
struct rebind {}; // Malformed `rebind` to hide the inherited one, if any.
};
Then 1072
is printed for me.
Related Topics
Calling a Random Number Generating Member Function Doesn't Produce Entirely Random Numbers
Aligning Static String Literals
Qt 5 and Qprocess Redirect Stdout with Signal/Slot Readyread
How to Compile C++11 Code with Orwell Dev-C++
Date/Time Conversion: String Representation to Time_T
Traceback a Pointer in C++ Code Gdb
Constraining the Existing Boost.Spirit Real_Parser (With a Policy)
Mixing Templates with Polymorphism
C++ Convert from Lpctstr to Const Char *
Why Does Sizeof(Int) Vary Across Different Operating Systems
Get a Reverse Iterator from a Forward Iterator Without Knowing the Value Type
How Can Cstring Be Passed to Format String %S
How to Add Zlib to an Existing Qt Installation
Msvcp140D.Dll Missing, Is There a Way Around