2016-12-08 8 views
0

コンテナをstd::map<int, std::set<std::string>>からstd::set<std::string>にフラット化する必要があり、構文が苦労しています。私がフラットンと言うとき、基本的にすべてのセットが縫い合わされた単一のstd::set<string>を作りたいと思っています - setは、私が必要とする重複する項目を防ぐでしょう。問題を解決するのを困難にする容器。コンパイラからの出力は非常に理解しにくいですが、ここでソースを以下に示します。std :: transformをstd :: transformを介してセットにフラット化

私はエラーを以下に示している私のコードのライブcoliru here

int main() 
{ 
    std::set<std::string> outputSet; 

    std::map<int, std::set<std::string>> inputMap = { 
     {1, {"a", "b", "c"}}, 
     {2, {"b", "c", "d"}} 
    }; 

    std::transform(inputMap.cbegin(), inputMap.cend(), 
     std::inserter(outputSet, outputSet.end()), 
     [](const std::map<int, std::set<std::string>>::value_type& rNext) { 
      return rNext.second; 
     });   
} 

を持っている:

In file included from /usr/local/include/c++/6.2.0/algorithm:62:0, 
       from main.cpp:4: 
/usr/local/include/c++/6.2.0/bits/stl_algo.h: In instantiation of '_OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation) [with _IIter = std::_Rb_tree_const_iterator<std::pair<const int, std::set<std::__cxx11::basic_string<char> > > >; _OIter = std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >; _UnaryOperation = main()::<lambda(const value_type&)>]': 
main.cpp:19:10: required from here 
/usr/local/include/c++/6.2.0/bits/stl_algo.h:4177:12: error: no match for 'operator=' (operand types are 'std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >' and 'std::set<std::__cxx11::basic_string<char> >') 
    *__result = __unary_op(*__first); 
    ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~ 
In file included from /usr/local/include/c++/6.2.0/bits/stl_algobase.h:67:0, 
       from /usr/local/include/c++/6.2.0/bits/stl_tree.h:63, 
       from /usr/local/include/c++/6.2.0/set:60, 
       from main.cpp:1: 
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:680:7: note: candidate: std::insert_iterator<_Container>& std::insert_iterator<_Container>::operator=(const typename _Container::value_type&) [with _Container = std::set<std::__cxx11::basic_string<char> >; typename _Container::value_type = std::__cxx11::basic_string<char>] 
     operator=(const typename _Container::value_type& __value) 
     ^~~~~~~~ 
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:680:7: note: no known conversion for argument 1 from 'std::set<std::__cxx11::basic_string<char> >' to 'const value_type& {aka const std::__cxx11::basic_string<char>&}' 
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:688:7: note: candidate: std::insert_iterator<_Container>& std::insert_iterator<_Container>::operator=(typename _Container::value_type&&) [with _Container = std::set<std::__cxx11::basic_string<char> >; typename _Container::value_type = std::__cxx11::basic_string<char>] 
     operator=(typename _Container::value_type&& __value) 
     ^~~~~~~~ 
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:688:7: note: no known conversion for argument 1 from 'std::set<std::__cxx11::basic_string<char> >' to 'std::set<std::__cxx11::basic_string<char> >::value_type&& {aka std::__cxx11::basic_string<char>&&}' 
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:629:11: note: candidate: constexpr std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >& std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >::operator=(const std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >&) 
    class insert_iterator 
      ^~~~~~~~~~~~~~~ 
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:629:11: note: no known conversion for argument 1 from 'std::set<std::__cxx11::basic_string<char> >' to 'const std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >&' 
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:629:11: note: candidate: constexpr std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >& std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >::operator=(std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >&&) 
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:629:11: note: no known conversion for argument 1 from 'std::set<std::__cxx11::basic_string<char> >' to 'std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >&&' 

答えて

2

あなたはそれ単一の要素を割り当てることがstd::inserterを期待を使用して作成しているstd::insert_iteratorコンテナに挿入されますが、set全体を割り当てようとしています。

std::for_eachあなたは

std::for_each(inputMap.cbegin(), inputMap.cend(), 
    [&](auto const& m) { 
     outputSet.insert(m.second.begin(), m.second.end()); 
    }); 
+0

、ニースエレガントでシンプルな、私は、のstd ::セットのSTD ::セットを必要とする変換どこhttp://coliru.stacked-crooked.com/a/391408db3b414728を参照することを考え出しましたcoliruデモにいくつか変更を加えました。ありがとう – johnco3

+0

これはまったく間違っていませんが、 'std :: for_each'の代わりに' for'を使用するほうが冗長ではありません。(1) 'cbegin()'と 'cend()'を書く必要はありません。それ; (2)ラムダなし。 しかし、この回答は、OPのコードで 'std :: transform'を使用した方が多くあります。 –

+0

@ダン "コンパイラはそれをする"とはどういう意味ですか? 'cbegin'の記述は、' inputMap'が 'const'でなければ冗長ではありません。 – Praetorian

1

ジャスト範囲for使用して物事をストレートフォワードな方法を行うやろうとしているものに適してい:スーパーエレガントではないかもしれない

for (const auto& v : inputMap) 
    for (const auto& e : v.second) 
     outputSet.insert(e); 

を。どちらのコンパイラエラーも発生しません。その作業によって、必要に応じて/別のものに調整することができます。例えば

for (const auto& v : inputMap) 
    outputSet.insert(v.second.cbegin(), v.second.cend());