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

如何初始化std::map中的就地键值对

  •  1
  • Setu  · 技术社区  · 1 年前

    我想将键值对插入到 std::map 具有 uint32_t 作为键类型和值的自定义类型。基于 documentation 属于 std::map ,我写了以下代码:

    #include <cstdint>
    #include <iostream>
    #include <map>
    
    struct Values
    {
            uint32_t a = 0;
            uint32_t b = 0;
    
            Values(uint32_t _x, uint32_t _y): a(_x), b(_y)
            {
                std::cout << __func__ << "(" << _x << ", " << _y ")" << std::endl;
            }
    };
    
    int main()
    {
            std::map<uint32_t, Values> data;
            for(uint32_t i = 0; i < 100; i++)
                    data.emplace(i, std::forward_as_tuple(i, i));
    
            return 0;
    }
    

    我正在编译代码 gcc 通过跑步

    gcc -O3 -std=c++23 -Wconversion -Wall -Wextra -Wpedantic -fanalyzer 
    

    然而,这段代码无法编译。

    Here's 指向编译器资源管理器的链接,您可以在其中查看以下内容的完整输出 gcc .

    gcc 正在抱怨:

    error: no matching function for call to 'construct_at(std::pair<const unsigned int, Values>*&, unsigned int&, std::tuple<unsigned int&, unsigned int&>)'
    

    为什么我会遇到这个错误,我该如何修复它?

    3 回复  |  直到 1 年前
        1
  •  5
  •   Remy Lebeau    1 年前
    std::map<uint32_t, Values> data;
    data.emplace(i, std::forward_as_tuple(i, i));
    

    emplace() 试图构建地图 value_type (即。 pair<uint32_t, const Values> )使用你传递给的论点袋 安置就位 。因此,它将尝试这样做:

    auto kv = pair<uint32_t, const Values>(i, std::forward_as_tuple(i, i));
    

    这是不对的。如果你想使用 pair 的完美转发构造函数,你需要说:

    auto kv = pair<uint32_t, const Values>(
      std::piecewise_construct,
      std::forward_as_tuple(i), // args for the first element
      std::forward_as_tuple(i, i) // args for the second element
    );
    

    这意味着你 安置就位 呼叫需要看起来像:

    data.emplace(
      std::piecewise_construct,
      std::forward_as_tuple(i), // args for the first element
      std::forward_as_tuple(i, i) // args for the second element
    );
    

    或者,如果你不介意构建 Values 稍早一点,你可以写:

    data.emplace(i, Values(i, i));
    

    其对应于:

    auto kv = pair<uint32_t, const Values>(
      i, // first element
      Values(i, i) // second element
    );
    

    甚至:

    data.insert(std::make_pair(i, Values(i, i)));
    
        2
  •  4
  •   Drew Dormann    1 年前

    std::map<uint32_t, Values>::emplace 使用其参数构造 std::pair<uint32_t, Values> .

    还有你的 i, std::forward_as_tuple(i, i) 不会构建那个 std::pair .

    您想使用 std::map::try_emplace ,这将移动/复制您的 uint32_t 钥匙和单独建造到位 Values 使用以下参数。

                 data.try_emplace(i, i, i);
    // first parameter is the key ^  ^^^^ all other parameters construct the value
    
        3
  •  3
  •   Remy Lebeau    1 年前

    Values 没有接受的构造函数 std::tuple .

    尝试指定 std::piecewise_construct emplace() 调用(参见示例 https://en.cppreference.com/w/cpp/utility/tuple/forward_as_tuple )例如:

    m.emplace(std::piecewise_construct,
              std::forward_as_tuple(i),
              std::forward_as_tuple(i, i));
    

    或者,你可以简单地不使用 std::tuple 根本没有,只是构建一个 价值观 直接,例如:

    m.emplace(i, Values(i, i));