一行 std::vector ctor 来自映射另一个向量

One line std::vector ctor from mapping another vector?

本文关键字:映射 另一个 向量 ctor std vector 一行      更新时间:2023-10-16

C++11

最后行应该有一行版本。

        typedef std::pair<T1, T2> impl_node;
        std::vector<impl_node> impl;
        /* do stuff with impl */
        std::vector<T1> retval(impl.size());
        std::transform(impl.cbegin(), impl.cend(), retval.begin(),
                         [](const impl_node& in) { return *in.first; });

我尝试编写某种自定义迭代器适配器,但类型越来越毛茸茸的。什么是"正确"的解决方案?(它可能推广到各种其他适配器。

这仍然是两行,但键入较少(在两种意义上):

std::vector<T1> retval(impl.size());
for (const auto& p : impl) retval.push_back(p.first); 

实际上,现在我看它,我更喜欢三行:

std::vector<T1> retval;
retval.reserve(impl.size());
for (const auto& p : impl) retval.push_back(p.first); 

(编辑以删除移动,因为没有证据表明它是合适的)

我不知道

有什么方法可以在一行中仅使用 C++11 中的标准 STL 来做到这一点,而无需先编写至少一个(模板化的)帮助程序函数。

您可能正在寻找一个概念,其中 2 个迭代器成为一个对象,并且C++开始支持类似于 .NET 中的 LINQ 扩展方法的行为:http://www.boost.org/doc/libs/1_52_0/libs/range/doc/html/index.html

通过使用插入迭代器,您可以获得至少一半的所需内容。

在不指定大小的情况下分配vector

std::vector<T1> retval;

。然后使用 back_inserter 填充它(从 #include <iterator> ):

std::transform(impl.cbegin(), impl.cend(), back_inserter(retval),[](const impl_node& in) { return *in.first; });

好吧,我们可以从这个开始:

template<typename Output, typename Input, typename Transformation>
auto transform( Input const& input, Transformation t )->Output {
  Output retval;
  retval.reserve(input.size());
  using std::cbegin; using std::cend;
  std::transform(cbegin(input), cend(input), std::back_inserter(retval));
  return retval;
}

然后做这样的事情:

namespace aux{
  using std::cbegin;
  template<typename T>
  auto adl_cbegin( T&& t )->decltype(cbegin(std::forward(t)));
}
template<typename Input, typename Transformation>
auto transform_vec( Input const& input, Transformation t )->
    std::vector<typename std::remove_ref<decltype(t(*adl_cbegin(input)))>::type>
{
  typedef std::vector<typename std::remove_ref<decltype(t(*adl_cbegin(input)))>::type> Output;
  Output retval;
//      retval.reserve(input.size()); -- need a way to do this if Input has an easy way to get size.  Too lazy to bother right now.
  using std::cbegin; using std::cend;
  std::transform(cbegin(input), cend(input), std::back_inserter(retval));
  return retval;
}

注意:这需要任何可迭代的东西(向量、数组、迭代器对)并产生一个然后,从那里升级到在输入范围内生成boost::transform_iterator std::pair,这样我们就可以将生成的转换插入到任意容器中,并且只有在实际取消引用迭代器时才执行转换工作。

或者,你知道,直接使用std::back_inserter(input)。 :) 这种方法的缺点是它不做保留,所以有性能下降。