// 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
emplace
oremplace_back
), here is an example implementation.You just need a way to detect whether
emplace
oremplace_back
is 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. ;)