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

使用cppyy处理右值指针与std::map时的问题求助

Cppyy中std::map结合右值引用/std::move的问题解决

问题描述

问题1:std::string存入std::map时触发TypeError

执行以下代码尝试将std::move处理后的std::string存入std::map<std::string, std::string>:

test_map = Cpp.std.map[Cpp.std.string, Cpp.std.string]()
test_string = Cpp.std.string("value")
test_map["key"] = Cpp.std.move(test_string)
print(test_map["key"])

报错信息:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[34], line 3
      1 test_map = Cpp.std.map[Cpp.std.string, Cpp.std.string]()
      2 test_string = Cpp.std.string("value")
----> 3 test_map["key"] = Cpp.std.move(test_string)
      4 print(test_map["key"])

TypeError: none of the 2 overloaded methods succeeded. Full details:
  std::string& std::map<std::string,std::string>::operator[](std::map<std::string,std::string>::key_type&& __k) =>
    logic_error: basic_string::_M_construct null not valid
  std::string& std::map<std::string,std::string>::operator[](const std::map<std::string,std::string>::key_type& __k) =>
    logic_error: basic_string::_M_construct null not valid

问题2:自定义模板类存入std::map时出现编译错误与TypeError

自定义模板类代码:

import cppyy
import cppyy.gbl as Cpp

cppyy.cppdef(r"""\
template<typename T>
class MyClass {
public:
    MyClass(T t) : m_data(t) {}
    T m_data;
};
""")

执行代码尝试存入std::move处理后的对象:

test_map = Cpp.std.map[Cpp.std.string, Cpp.MyClass['double']]()
myClass  = Cpp.MyClass['double'](5.0)
test_map["key"] = Cpp.std.move(myClass)
print(test_map["key"])

报错信息:

input_line_50:6:86: error: no member named 'operator[]' in 'std::map<std::__cxx11::basic_string<char>, MyClass<double>, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, MyClass<double> > > >'
      new (ret) (MyClass<double>*) (&((std::map<std::string,MyClass<double> >*)obj)->operator[]((std::string&&)*(std::string*)args[0]));
                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  ^
input_line_50:10:55: error: no member named 'operator[]' in 'std::map<std::__cxx11::basic_string<char>, MyClass<double>, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, MyClass<double> > > >'
      ((std::map<std::string,MyClass<double> >*)obj)->operator[]((std::string&&)*(std::string*)args[0]);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  ^
input_line_51:6:86: error: no member named 'operator[]' in 'std::map<std::__cxx11::basic_string<char>, MyClass<double>, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, MyClass<double> > > >'
      new (ret) (MyClass<double>*) (&((std::map<std::string,MyClass<double> >*)obj)->operator[]((const std::string&)*(const std::string*)args[0]));
                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  ^
input_line_51:10:55: error: no member named 'operator[]' in 'std::map<std::__cxx11::basic_string<char>, MyClass<double>, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, MyClass<double> > > >'
      ((std::map<std::string,MyClass<double> >*)obj)->operator[]((const std::string&)*(const std::string*)args[0]);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  ^

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[45], line 3
      1 test_map = Cpp.std.map[Cpp.std.string, Cpp.MyClass['double']]()
      2 myClass  = Cpp.MyClass['double'](5.0)
----> 3 test_map["key"] = Cpp.std.move(myClass)
      4 print(test_map["key"])

TypeError: none of the 2 overloaded methods succeeded. Full details:
  MyClass<double>& std::map<std::string,MyClass<double> >::operator[](std::map<std::string,MyClass<double> >::key_type&& __k) =>
    ReferenceError: none of the 2 overloaded methods succeeded. Full details:
  attempt to access a null-pointer
  attempt to access a null-pointer
  MyClass<double>& std::map<std::string,MyClass<double> >::operator[](const std::map<std::string,MyClass<double> >::key_type& __k) =>
    TypeError: none of the 2 overloaded methods succeeded. Full details:
  MyClass<double>& MyClass<double>::operator=(MyClass<double>&&) =>
    ValueError: could not convert argument 1 (object is not an rvalue)
  attempt to access a null-pointer

解决方案

问题1修复:避免使用operator[],改用emplace/insert

std::map::operator[]的逻辑是:若key不存在则默认构造一个value,再返回引用供赋值。cppyy在处理这个流程结合右值引用时会触发构造错误。直接用emplace原地构造键值对,或insert插入移动后的pair即可解决:

test_map = Cpp.std.map[Cpp.std.string, Cpp.std.string]()
test_string = Cpp.std.string("value")
# 方案1:用emplace直接构造,自动处理右值
test_map.emplace(Cpp.std.move(Cpp.std.string("key")), Cpp.std.move(test_string))
# 方案2:用insert插入pair
# test_map.insert({Cpp.std.string("key"), Cpp.std.move(test_string)})
# 用at()访问元素,避免operator[]的默认构造逻辑
print(test_map.at(Cpp.std.string("key")))

问题2修复:补充类的必要构造/赋值函数,或跳过operator[]

核心原因

  1. std::map::operator[]要求value类型必须支持默认构造,你的MyClass没有默认构造函数,导致cppyy无法找到对应的operator[]重载,触发编译错误。
  2. cppyy处理右值赋值时,需要类有明确的移动赋值运算符。

修复方案

方案A:补充类的默认构造和移动赋值(兼容operator[])

修改自定义类代码:

import cppyy
import cppyy.gbl as Cpp

cppyy.cppdef(r"""\
template<typename T>
class MyClass {
public:
    MyClass() : m_data(T{}) {} // 添加默认构造函数
    MyClass(T t) : m_data(t) {}
    // 添加移动赋值运算符
    MyClass& operator=(MyClass&& other) noexcept {
        if (this != &other) {
            m_data = std::move(other.m_data);
        }
        return *this;
    }
    T m_data;
};
""")

之后可以使用operator[],但更推荐用emplace:

test_map = Cpp.std.map[Cpp.std.string, Cpp.MyClass['double']]()
myClass = Cpp.MyClass['double'](5.0)
test_map.emplace(Cpp.std.string("key"), Cpp.std.move(myClass))
print(test_map.at(Cpp.std.string("key")).m_data)
方案B:跳过operator[],直接用emplace/insert(无需修改类)

如果不想修改MyClass,直接用emplace插入键值对,它不需要value支持默认构造:

test_map = Cpp.std.map[Cpp.std.string, Cpp.MyClass['double']]()
myClass = Cpp.MyClass['double'](5.0)
test_map.emplace(Cpp.std.string("key"), Cpp.std.move(myClass))
print(test_map.at(Cpp.std.string("key")).m_data)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 21:47:48