2

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; });

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

4

4 回答 4

3

这仍然是两行,但打字更少(在两种意义上):

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); 

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

于 2012-12-13T21:47:29.253 回答
0

我不知道有一种方法可以仅使用 C++11 中的标准 STL 在一行中执行此操作,而无需先编写至少一个(模板化的)辅助函数。

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

于 2012-12-13T21:28:27.580 回答
0

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

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

std::vector<T1> retval;

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

std::transform(impl.cbegin(), impl.cend(), back_inserter(retval),[](const impl_node& in) { return *in.first; });
于 2012-12-13T21:46:56.227 回答
0

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

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;
}

注意:这需要任何可迭代的东西(向量、数组、迭代器对)并生成 a 并从那里升级到在输入范围上生成 a std::pairof boost::transform_iterator,因此我们可以将生成的转换插入任意容器中,我们只做如果我们实际上取消引用迭代器,则转换工作。

或者,你知道,直接使用std::back_inserter(input)。:) 这种方法的缺点是它不做储备,所以会影响性能。

于 2012-12-13T21:50:22.880 回答