【问题标题】:flattening a std::map to a set via std::transform通过 std::transform 将 std::map 展平为一个集合
【发布时间】:2016-12-08 21:32:23
【问题描述】:

我需要将容器从 std::map<int, std::set<std::string>> 展平为 std::set<std::string>,但我在语法上遇到了困难。当我说扁平化时,我基本上想制作一个 std::set<string> 并将所有集合缝合在一起 - (set 将防止重复条目,这是我需要的)我正在尝试基于此 question 中的答案但我的值类型是一个容器,它使问题更难解决。编译器的输出很难看懂,下面是源码。

我有一个活的我的代码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> > >&&'

【问题讨论】:

    标签: c++ c++11 stl c++14 stl-algorithm


    【解决方案1】:

    您使用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());
        });
    

    【讨论】:

    【解决方案2】:

    使用 range 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());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-07
      • 1970-01-01
      • 1970-01-01
      • 2019-10-06
      • 2016-04-22
      • 2018-11-19
      • 1970-01-01
      相关资源
      最近更新 更多