You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用emplace向std::map插入含mutex的struct时触发C2660错误求助

std::map emplace插入含锁的结构体失败问题分析与解决

问题代码

struct Queue_ctx {
  std::mutex qu_mutex;
  std::condition_variable qu_cv;
  std::queue<std::vector<std::byte>> qu;
};

std::map<std::string, Queue_ctx> incoming_q_map;
Queue_ctx qctx;
std::vector<std::byte> vect(100);
qctx.qu.push(vect);
incoming_q_map.emplace("actor", qctx);

编译错误信息

error C2660: 'std::pair<const std::string,main::Queue_ctx>::pair': function does not take 2 arguments
 
message : see declaration of 'std::pair<const std::string,main::Queue_ctx>::pair'

message : see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,const char(&)[6],main::Queue_ctx&>(_Alloc &,_Objty *const ,const char (&)[6],main::Queue_ctx &)' being compiled
        with
        [
            _Alloc=std::allocator<std::_Tree_node<std::pair<const std::string,main::Queue_ctx>,std::_Default_allocator_traits<std::allocator<std::pair<const std::string,main::Queue_ctx>>>::void_pointer>>,
            _Ty=std::pair<const std::string,main::Queue_ctx>,
            _Objty=std::pair<const std::string,main::Queue_ctx>
        ]

问题原因

  1. std::map的元素本质是pair:std::map的每个元素都是std::pair<const std::string, Queue_ctx>类型,emplace的作用是在map的内存空间中原地构造这个pair,因此编译器会尝试将你传入的参数转发给pair的构造函数。
  2. Queue_ctx不可拷贝:std::mutex和std::condition_variable是不可拷贝、不可移动的类型,编译器会自动删除Queue_ctx的拷贝构造函数和移动构造函数。当调用emplace("actor", qctx)时,需要用qctx拷贝构造pair的第二个成员,但拷贝构造函数已被删除,导致找不到匹配的pair构造函数,触发C2660错误。
  3. 默认构造函数没问题:Queue_ctx的默认构造函数是存在的,会正确初始化mutex、condition_variable和queue,但这和拷贝构造被删除的问题无关。

修复方案

因为Queue_ctx无法拷贝或移动,只能在map内部原地构造,然后直接操作map中的实例:

方案一:先构造空实例,再添加数据

std::map<std::string, Queue_ctx> incoming_q_map;

// 原地构造空的Queue_ctx实例
auto [iter, success] = incoming_q_map.emplace("actor", Queue_ctx{});
// C++17之前写法:
// auto iter = incoming_q_map.emplace("actor", Queue_ctx{}).first;

// 获取map中Queue_ctx的引用,向队列添加数据
std::vector<std::byte> vect(100);
iter->second.qu.push(vect);

方案二:使用piecewise_construct原地构造(自定义初始化场景)

如果需要在构造时就初始化qu成员,可以用std::piecewise_construct分别构造pair的两个部分:

std::map<std::string, Queue_ctx> incoming_q_map;
std::vector<std::byte> vect(100);

incoming_q_map.emplace(
    std::piecewise_construct,
    std::forward_as_tuple("actor"), // 构造key部分
    std::forward_as_tuple(
        std::mutex{},               // 初始化mutex
        std::condition_variable{},  // 初始化condition_variable
        std::queue<std::vector<std::byte>>{} // 初始化queue,也可传入可移动的已有队列
    )
);

// 后续通过引用操作队列
auto& qctx = incoming_q_map["actor"];
qctx.qu.push(std::move(vect));

补充说明

  • 尝试make_pair无效,本质原因还是Queue_ctx不可拷贝,make_pair同样需要拷贝qctx,因此无法通过编译。
  • 注释掉qu_mutex和qu_cv后,Queue_ctx只剩可拷贝的std::queue,编译器会生成默认拷贝构造函数,因此emplace可以正常工作。

内容的提问来源于stack exchange,提问作者irsis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 15:20:23