使用emplace与算法,如std :: fill

编程入门 行业动态 更新时间:2024-10-23 21:26:55
本文介绍了使用emplace与算法,如std :: fill的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我使用 vector :: emplace_back 以避免在填充向量时构造时态对象。这里有一个简化版本:

I have used vector::emplace_back in order to avoid constructing temporal objects while filling a vector. Here you have a simplified version:

class Foo { public: Foo(int i, double d) : i_(i), d_(d) {} /* ... */ }; std::vector<Foo> v; v.reserve(10); for (int i = 0; i < 10; i++) v.emplace_back(1, 1.0);

但我想使用 std :: fill_n 改为:

v.reserve(10); std::fill_n(std::back_inserter(v), 10, Foo(1, 1.0));

这样,临时副本将被创建。在这种情况下,我不知道如何使用 emplace 。我想我需要像 std :: back_emplacer ,但我找不到这样的东西。是C ++ 11的那一部分,但是在GCC中没有实现?如果它不是C ++ 11的一部分,有没有其他方法来做到这一点?

In this way, temporal copies will be created, though. I do not know how to use emplace in this situation. I guess I would need something like std::back_emplacer, but I could not find such a thing. Is that part of C++11, but not implemented in GCC yet? If it is not part of C++11, is there any other way to do that?

推荐答案

通常使用元组来简化传递一个可变数目的项目(在这种情况下,参数转到 emplace_back ),其中一个小技巧来打开元组回来。因此,可以通过要求用户使用元组工厂函数( std :: make_tuple )来编写 back_emplacer code>, std :: tie , std :: forward_as_tuple ) >

It's common to use tuples to ease the pass a variadic number of items (in this case, parameters to forward to emplace_back), with a little technique to unpack the tuple back. As such it is possible to write a back_emplacer utility by requiring the user to make use of the tuple factory functions (one of std::make_tuple, std::tie, std::forward_as_tuple) where it make sense:

#include <type_traits> #include <tuple> // Reusable utilites template<typename T> using RemoveReference = typename std::remove_reference<T>::type; template<typename T> using Bare = typename std::remove_cv<RemoveReference<T>>::type; template<typename Out, typename In> using WithValueCategoryOf = typename std::conditional< std::is_lvalue_reference<In>::value , typename std::add_lvalue_reference<Out>::type , typename std::conditional< std::is_rvalue_reference<Out>::value , typename std::add_rvalue_reference<Out>::type , Out >::type >::type; template<int N, typename Tuple> using TupleElement = WithValueCategoryOf< typename std::tuple_element<N, RemoveReference<Tuple>>::type , Tuple >; // Utilities to unpack a tuple template<int... N> struct indices { using next = indices<N..., sizeof...(N)>; }; template<int N> struct build_indices { using type = typename build_indices<N - 1>::type::next; }; template<> struct build_indices<0> { using type = indices<>; }; template<typename Tuple> constexpr typename build_indices<std::tuple_size<Bare<Tuple>>::value>::type make_indices() { return {}; } template<typename Container> class back_emplace_iterator { public: explicit back_emplace_iterator(Container& container) : container(&container) {} template< typename Tuple // It's important that a member like operator= be constrained // in this case the constraint is delegated to emplace, // where it can more easily be expressed (by expanding the tuple) , typename = decltype( emplace(std::declval<Tuple>(), make_indices<Tuple>()) ) > back_emplace_iterator& operator=(Tuple&& tuple) { emplace(*container, std::forward<Tuple>(tuple), make_indices<Tuple>()); return *this; } template< typename Tuple , int... Indices , typename std::enable_if< std::is_constructible< typename Container::value_type , TupleElement<Indices, Tuple>... >::value , int >::type... > void emplace(Tuple&& tuple, indices<Indices...>) { using std::get; container->emplace_back(get<Indices>(std::forward<Tuple>(tuple))...); } // Mimic interface of std::back_insert_iterator back_emplace_iterator& operator*() { return *this; } back_emplace_iterator& operator++() { return *this; } back_emplace_iterator operator++(int) { return *this; } private: Container* container; }; template<typename Container> back_emplace_iterator<Container> back_emplacer(Container& c) { return back_emplace_iterator<Container> { c }; }

代码演示可用。在你的case你会想调用 std :: fill_n(back_emplacer(v),10,std :: forward_as_tuple(1,1.0)); ( std :: make_tuple 也是可以接受的)。你还需要通常的迭代器的东西使功能完成 - 我建议Boost.Iterators。

A demonstration of the code is available. In your case you'd want to call std::fill_n(back_emplacer(v), 10, std::forward_as_tuple(1, 1.0)); (std::make_tuple is also acceptable). You'd also want the usual iterator stuff to make the feature complete -- I recommend Boost.Iterators for that.

我必须真正强调,但是,这样的实用程序不'当与 std :: fill_n 一起使用时会带来很多。在你的情况下,它会保存临时 Foo 的结构,有利于一个引用的元组(一个值的元组,如果你使用 std :: make_tuple )。我留给读者找到一些其他算法, back_emplacer 将是有用的。

I must really stress however that such a utility doesn't bring much when used with std::fill_n. In your case it would save the construction of the temporary Foo, in favour of a tuple of references (a tuple of values if you were to use std::make_tuple). I leave it to the reader to find some other algorithm where back_emplacer would be useful.

更多推荐

使用emplace与算法,如std :: fill

本文发布于:2023-11-30 01:29:47,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1648268.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:算法   emplace   fill   std

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!