-1
\$\begingroup\$

I have function which returns a vector or strings (values from an sqlite3 table).

For each of those strings I need to generate a Qt Checkbox, if it does not exist yet.

My first version looks like this:

const auto results = queryStrings(QStringLiteral("select ..."));

const auto pred = [this](const QString& name) {
    return this->findChild<QCheckBox*>(name + QStringLiteral("_CB")) == nullptr;
};

for (const auto& sourceName : boost::adaptors::filter(results, pred))
{
  // create checkbox ...
}

Alternatively I could use something like this:

const auto pred = [this](const QString& name) {
    return this->findChild<QCheckBox*>(name + QStringLiteral("_CB")) == nullptr;
};

const auto results = queryStrings(QStringLiteral("select ..."), pred);

for (const auto& typeName : results)
{
  // create checkbox ...
}

As this code can be called quite frequently, I was wondering if the use of boost::adaptors::filter comes with a overhead or if the second second version with the predicate passed to the queryStrings function is better.

\$\endgroup\$
1
\$\begingroup\$

You won't know for sure which is the fastest unless you test it. And you won't know if that portion of the code is what matters unless you profile its runtime execution. When you care about performance, testing in real time is the only way.

If you look at it from a more theoretical perspective, then filtering is a O(n) activity, and you won't be able to do much better than the simplest way:

for (const auto& name : results) {
    if (pred(name)) ...
}

You can do very fancy things, have lambdas with this capture, Boost ranges prefiguration, etc. and they are good things, perhaps more readable once you're used to those idioms, but you won't be more efficient.

That said, your second version should do better if queryStrings is able not to allocate memory for table records which don't satisfy the predicate.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.