c++ - Is there a way to emplace return value? -
// version 1 struct range { int begin, end; }; inline range getrange() { int newbegin, newend; // 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; // calculations ranges.emplace_back(newbegin, newend); } };
version 2 faster version 1.
fact is, getrange()
used multiple classes. if apply version 2, there lot of code duplication.
also, cannot pass ranges
non-const reference getrange()
, other classes use std::stack
instead of std::vector
. have create multiple overloads , have more code duplications.
is there common way/idiom emplace return value?
following our discussion in comments using sfinae allow emplacement on type of container (whether supports emplace
or emplace_back
), here example implementation.
you need way detect whether emplace
or emplace_back
available, , dispatch call accordingly. purpose, we'll use sfinae:
namespace detail { template<typename t, typename... args> auto emplace_impl(int, t& c, args&&... pp) -> decltype(c.emplace_back(std::forward<args>(pp)...)) { return c.emplace_back(std::forward<args>(pp)...); } template<typename t, typename... args> auto emplace_impl(long, t& c, args&&... pp) -> decltype(c.emplace(std::forward<args>(pp)...)) { return c.emplace(std::forward<args>(pp)...); } } // namespace detail template<typename t, typename... args> auto emplace(t& c, args&&... pp) -> decltype(detail::emplace_impl(0, c, std::forward<args>(pp)...)) { return detail::emplace_impl(0, c, std::forward<args>(pp)...); }
kudos @dyp provided much nicer , shorter c++11 solution (see comments). previous traits-based solutions (revisions 3 & 4) lot more verbose.
using quite straightforward:
template<typename container> void test_emplace() { container c; emplace(c, 3); } int main() { test_emplace<std::queue<int>>(); test_emplace<std::stack<int>>(); test_emplace<std::deque<int>>(); test_emplace<std::list<int>>(); test_emplace<std::vector<int>>(); }
i'll let bridge gap between test_emplace()
usage example , actual code, shouldn't hard now. ;)
Comments
Post a Comment