• <tfoot id='nu3jc'></tfoot>
  • <small id='nu3jc'></small><noframes id='nu3jc'>

      <legend id='nu3jc'><style id='nu3jc'><dir id='nu3jc'><q id='nu3jc'></q></dir></style></legend>

        <i id='nu3jc'><tr id='nu3jc'><dt id='nu3jc'><q id='nu3jc'><span id='nu3jc'><b id='nu3jc'><form id='nu3jc'><ins id='nu3jc'></ins><ul id='nu3jc'></ul><sub id='nu3jc'></sub></form><legend id='nu3jc'></legend><bdo id='nu3jc'><pre id='nu3jc'><center id='nu3jc'></center></pre></bdo></b><th id='nu3jc'></th></span></q></dt></tr></i><div id='nu3jc'><tfoot id='nu3jc'></tfoot><dl id='nu3jc'><fieldset id='nu3jc'></fieldset></dl></div>
          <bdo id='nu3jc'></bdo><ul id='nu3jc'></ul>

        将 emplace 与 std::fill 等算法一起使用

        时间:2024-08-14

          <small id='6a160'></small><noframes id='6a160'>

              <bdo id='6a160'></bdo><ul id='6a160'></ul>
                  <tbody id='6a160'></tbody>
                <tfoot id='6a160'></tfoot>

              1. <i id='6a160'><tr id='6a160'><dt id='6a160'><q id='6a160'><span id='6a160'><b id='6a160'><form id='6a160'><ins id='6a160'></ins><ul id='6a160'></ul><sub id='6a160'></sub></form><legend id='6a160'></legend><bdo id='6a160'><pre id='6a160'><center id='6a160'></center></pre></bdo></b><th id='6a160'></th></span></q></dt></tr></i><div id='6a160'><tfoot id='6a160'></tfoot><dl id='6a160'><fieldset id='6a160'></fieldset></dl></div>
              2. <legend id='6a160'><style id='6a160'><dir id='6a160'><q id='6a160'></q></dir></style></legend>

                  本文介绍了将 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_tuplestd::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 }; }
                  

                  代码演示可用.在你的情况下,你想调用 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 等算法一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:std::vector :无法将“std::ostream {aka std::basic_ostream<cha 下一篇:C++ STL:STL 容器上的哪种迭代方法更好?

                  相关文章

                    <bdo id='tgFl2'></bdo><ul id='tgFl2'></ul>
                    <i id='tgFl2'><tr id='tgFl2'><dt id='tgFl2'><q id='tgFl2'><span id='tgFl2'><b id='tgFl2'><form id='tgFl2'><ins id='tgFl2'></ins><ul id='tgFl2'></ul><sub id='tgFl2'></sub></form><legend id='tgFl2'></legend><bdo id='tgFl2'><pre id='tgFl2'><center id='tgFl2'></center></pre></bdo></b><th id='tgFl2'></th></span></q></dt></tr></i><div id='tgFl2'><tfoot id='tgFl2'></tfoot><dl id='tgFl2'><fieldset id='tgFl2'></fieldset></dl></div>

                      <legend id='tgFl2'><style id='tgFl2'><dir id='tgFl2'><q id='tgFl2'></q></dir></style></legend>
                      <tfoot id='tgFl2'></tfoot>
                    1. <small id='tgFl2'></small><noframes id='tgFl2'>