代码之家  ›  专栏  ›  技术社区  ›  user6646922

将std::pair引用从std::map传递到接受std::pair引用的函数

  •  0
  • user6646922  · 技术社区  · 6 年前

    编辑:第一个问题的答案是使用std::pair。关于第二个问题(标记为“奖金问题”)有什么想法吗?

    使用以下代码:

    #include <map>
    #include <vector>
    
    void foo(std::pair<int, int>& p)  // EDIT: it needs to be non-const
    {}
    
    int main()
    {
        std::pair<int, int> p{1,2};
        foo(p);
        std::vector<std::pair<int, int>> v{{1,2}};
        for (auto& element : v)
        {
            foo(element);  // works fine
        }
    
        std::map<int, int> m{std::make_pair(1,2)};
        //std::map<int, int> m2{{1,2}};
        for (auto& element : m)  // the problematic loop
        {
            foo(element);
        }
    
        return 0;
    }
    

    在后一个for循环中,我得到m的以下消息:

    错误:对'std::pair&类型的引用的初始化无效 “std::pair”类型的表达式

    在那个地方有M2的情况如下:

    错误:类型的非常量引用的初始化无效 'std::pair&'来自'std::pair'类型的值

    为什么?

    附加问题: 我发现非常奇怪的是,当m2的初始化没有被注释掉,for循环保持不变(其中仍然有m,m2从未使用过)时,错误消息从

    错误:对'std::pair&类型的引用的初始化无效 “std::pair”类型的表达式

    错误:类型的非常量引用的初始化无效 'std::pair&'来自'std::pair'类型的值

    我很想知道你对此的想法。我用onlinegdb.com测试了这段代码

    3 回复  |  直到 6 年前
        1
  •  4
  •   Useless    6 年前

    the documentation 我是说,

    map::value_type = std::pair<const Key, T>
    

    意思

    map<int,int>::value_type = pair<const int, int>
    

    所以编译器可以隐式地转换类型为 pair<const int,int>& 到类型为的临时(rvalue) pair<int,int> ,但这不能由非常量引用传递给函数。

    或者将参数类型更改为 pair<const int,int> ,或按价值计算。


    作为参考,GCC 6.3提供了这一信息量非常大的错误:

    prog.cpp: In function ‘int main()’:
    prog.cpp:21:13: error: invalid initialization of non-const reference of type ‘std::pair<int, int>&’ from an rvalue of type ‘std::pair<int, int>’
             foo(element);
                 ^~~~~~~
    In file included from /usr/include/c++/6/bits/stl_algobase.h:64:0,
                     from /usr/include/c++/6/bits/stl_tree.h:63,
                     from /usr/include/c++/6/map:60,
                     from prog.cpp:1:
    /usr/include/c++/6/bits/stl_pair.h:272:19: note:   after user-defined conversion: constexpr std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U1 = const int; _U2 = int; typename std::enable_if<(std::_PCC<((! std::is_same<_T1, _U1>::value) || (! std::is_same<_T2, _U2>::value)), _T1, _T2>::_ConstructiblePair<_U1, _U2>() && std::_PCC<((! std::is_same<_T1, _U1>::value) || (! std::is_same<_T2, _U2>::value)), _T1, _T2>::_ImplicitlyConvertiblePair<_U1, _U2>()), bool>::type <anonymous> = 1u; _T1 = int; _T2 = int]
             constexpr pair(const pair<_U1, _U2>& __p)
                       ^~~~
    prog.cpp:4:6: note:   initializing argument 1 of ‘void foo(std::pair<int, int>&)’
     void foo(std::pair<int, int>& p)
    

    特别要注意关于 自定义转换后

        2
  •  6
  •   Maxim Egorushkin    6 年前

    The container makes the key const (这适用于所有关联容器):

    value_type    std::pair<const Key, T>
    

    所以应该是 void foo(std::pair<int const, int>& p) 是的。

        3
  •  3
  •   Olivier Sohn    6 年前

    不允许修改映射的键,因此可以:

    #include <map>
    #include <vector>
    
    // foo can modify the first value of the pair
    void foo(std::pair<int, int>& p)
    {}
    // fooConstFirst cannot modify the first value of the pair
    void fooConstFirst(std::pair<const int, int>& p)
    {}
    
    int main()
    {
      std::pair<int, int> p{1,2};
      foo(p);
      std::vector<std::pair<int, int>> v{{1,2}};
      for (auto& element : v)
      {
        foo(element);
      }
    
      std::map<int, int> m{std::make_pair(1,2)};
      for (auto& element : m)
      {
        fooConstFirst(element);
      }
    
      return 0;
    }