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 QString
s 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With