2012-12-13 38 views
2

C++ 11一行std :: vector ctor映射另一個向量?

應該有最後一個兩個行的單行版本。

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

我試着寫一些自定義迭代器適配器,並且類型變得毛茸茸的。什麼是「正確」的解決方案? (它可能推廣到各種其他適配器。)

+2

你見過['boost :: transform_iterator'](http://www.boost.org/libs/iterator/doc/transform_iterator.html)嗎? (而你的'impl'是函數聲明,而不是對象。) – ildjarn

+1

'std :: vector impl();'應該可能是'std :: vector impl;' –

+0

最後兩行*?或者最後兩個*聲明*? –

回答

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

(編輯,因爲沒有證據證明它是適當去除移動)

+0

明確使用'reserve'代替'retval'中的默認結構。我沒有這樣想過,因爲我的T1是標量。) –

0

我不知道在一行中只使用來自C++ 11的標準STL來完成此操作的一種方式,而無需至少編寫一個(模板化)幫助器功能第一。

你可能會尋找一個概念,在這裏2個迭代器成爲一個對象和C++開始支持類似.NET的LINQ擴展方法的行爲: http://www.boost.org/doc/libs/1_52_0/libs/range/doc/html/index.html

0

你可以得到的東西,你至少一半」通過使用插入迭代器重新尋找。

分配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; }); 
+1

我更喜歡第三行做'reserve'。 –

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

注:這需要什麼迭代(向量,數組,迭代器對)並生成一個 ,然後從那裏升級到在輸入範圍內生成std::pair,boost::transform_iterator,因此我們可以將生成的轉換插入到任意容器中,並且我們只進行轉換工作如果我們實際上取消引用迭代器。

或者,您知道,直接使用std::back_inserter(input)即可。 :)這種方法的缺點是它沒有做保留,所以有性能點擊。

相關問題