Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can capture-by-reference in expression templates coexist with type deduction?

Tags:

Expression templates are often used as an optimization technique to avoid the creation of temporary objects. They defer constructing the complete object until the template is used in an assignment or initialization. This finds use in string builders, linear algebra packages, etc.

To avoid expensive copies, the expression template class can capture the bigger arguments by reference. I'll use Qt's QStringBuilder as an example.

It works when the references outlive the expression template:

QString foo = QString("A") + QString("B");
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
              QStringBuilder<QConcatenable<QString>,
                             QConcatenable<QString>>

The conversion and resolving of the expression template happens at the assignment. The string temporaries outlive the assignment.

Alas, we run into trouble as soon as the expression template type is inferred instead of the target type:

// WORKS
QString foo = []() -> QString { return QString("A") + QString("B"); }();
// FAILS
QString foo = []{ return QString("A") + QString("B"); }();

And also:

auto foo = QString("A") + QString("B");
// foo holds references to strings that don't exist anymore
QString bar = foo; // oops

One solution is for the builder to hold copies of objects. Since QStrings here are implicitly shared, their copying is cheap, although still more expensive than holding a reference. Suppose, though, that the arguments were std::string: you'd definitely not want to copy them unless necessary.

Is there any technique that could be used to detect that a complete template expression is not immediately resolved and must copy the data is thus far only held a reference to?

Note: I'm not asking about any particular existing implementation of expression templates. I only use QStringBuilder as a motivating example. This isn't a Qt question, or an eigen question, etc. The title is the question, pretty much.