Using a temporary object without storing it in variable

Viewed 154

Let's take an example where we need to insert the vector returned from a function to another vector:

const std::vector<int> getvec(){
    return {1, 2, 3};
}

// in main...
std::vector<int> foo{ 11, 12 };
auto bar = getvec();
foo.insert(foo.end(), bar.begin(), bar.end());

The fact that the bar variable needs to be referenced twice in the insert() method makes it necessary to have the vector stored as a variable (we could otherwise do foo.myinsert(getvec()) should there be such an interface).

It is a bit annoying to me that in such a case, we need to introduce a variable foo in the main scope which is not meant to be used again in the rest of the code, as it occupies the memory and also pollutes the namespace. Especially a problem if we are talking about with a large "temporary" object.

Is there a standard approach to deal with that? We could define a function that take the "temporary" object only once so that we can directly feed function output to it, but would be difficult to manage if we need to define such function for every similar scenario. Also as in this example we are not able to define a member function for vector class.

Alternatively what using braces to limit the scope of the "temporary" part of the insertion but I would like to know if any caveat here.

vector<int> foo{ 11, 12 };
{ // extra brace here
    auto bar = getvec();
    foo.insert(foo.end(), bar.begin(), bar.end());
} // extra brace here
3 Answers

Not the prettiest solution, but you could use a temporary lambda instead of a separate function, and declaring and invoking it in the same statement avoids the need for braces to limit its scope.

const std::vector<int> getvec(){
    return {1, 2, 3};
}

// in main...
std::vector<int> foo{ 11, 12 };
[&](const auto &bar){ foo.insert(foo.end(), bar.begin(), bar.end()); }(getvec());

Live Demo

You could write a little template function to do this, which takes a vector by const reference (which can bind to a temporary and extend its lifetime):

template<typename C>
void append(std::vector<C> &invec, const std::vector<C> &temp)
{
    invec.insert(std::end(invec), std::begin(temp), std::end(temp));
}

and this could be used for all other types of vectors. Then you can call it like this:

append(foo, getvec());

Working demo here.

You can make strings of other things than char. Thru basic_string<int> you can access string::append ( and other things )

using strint = std::basic_string<int>;
strint getVec () {
    return { 1, 2, 3, 4, 5 };
}

strint foo{ 6, 7 };
foo += getVec();

https://godbolt.org/z/h4naTa

Related