// VERSION 1
struct Range { int begin, end; };
inline Range getRange()
{
int newBegin, newEnd;
// do calculations
return {newBegin, newEnd};
}
struct Test
{
std::vector<Range> ranges;
inline void intensive()
{
ranges.push_back(getRange());
// or ranges.emplace_back(getRange());
// (gives same performance results)
}
};
// VERSION 2
struct Range { int begin, end; };
struct Test
{
std::vector<Range> ranges;
inline void intensive()
{
int newBegin, newEnd;
// do calculations
ranges.emplace_back(newBegin, newEnd);
}
};
Version 2 is always faster than version 1.
Fact is, getRange() is used by multiple classes. If I were to apply version 2, there would be a lot of code duplication.
Also, I cannot pass ranges as a non-const reference to getRange(), as some other classes use a std::stack instead of a std::vector. I would have to create multiple overloads and have more code duplications.
Is there a common way/idiom to emplace the return value?
Following our discussion in the comments about using SFINAE to allow emplacement on any type of container (whether it supports
emplaceoremplace_back), here is an example implementation.You just need a way to detect whether
emplaceoremplace_backis available, and dispatch the call accordingly. For this purpose, we'll use SFINAE:Kudos to @DyP who provided this much nicer and shorter C++11 solution (see comments). The previous traits-based solutions (revisions 3 & 4) were a lot more verbose.
Using it is quite straightforward:
I'll let you bridge the gap between my
test_emplace()usage example and your actual code, but it shouldn't be too hard now. ;)