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

使用std::back_inserter处理引用失效,包装std::set_intersection遇编译错误

包装std::set_intersection时的编译错误及优化需求

错误复现代码

%%cython -a -+

from libcpp.vector cimport vector
from libcpp.algorithm cimport set_intersection
from libcpp.iterator cimport back_inserter

cdef vector[int] x, y, z

cdef intersection(vector[int]* i1, vector[int]* i2, vector[int]* o):
    set_intersection(i1.begin(), i1.end(), i2.begin(), i2.end(), back_inserter(o[0]))

x = [1, 2, 3]
y = [1, 3, 5]

intersection(&x, &y, &z)
print(z)

编译错误信息

C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\iterator(41): error C2825: '_Container': must be a class or namespace when followed by '::'
C:\Users\<redacted>\.ipython\cython\_cython_magic_0c03d6fb9770602e2805cbe448ec2c32fdd0e67d.cpp(2279): note: see reference to class template instantiation 'std::back_insert_iterator<std::vector<int,std::allocator<int>> &>' being compiled
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\iterator(41): error C2510: '_Container': left of '::' must be a class/struct/union
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\iterator(41): error C2182: '_Val': illegal use of type 'void'
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\iterator(46): error C2825: '_Container': must be a class or namespace when followed by '::'
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\iterator(46): error C2510: '_Container': left of '::' must be a class/struct/union
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\iterator(46): error C2182: '_Val': illegal use of type 'void'
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\iterator(64): error C2528: 'container': pointer to reference is illegal

临时可行但存在额外拷贝的代码

%%cython -a -+

from libcpp.vector cimport vector
from libcpp.algorithm cimport set_intersection
from libcpp.iterator cimport back_inserter

cdef vector[int] x, y, z

cdef intersection(vector[int]* i1, vector[int]* i2, vector[int]* o):
    cdef vector[int] o2
    set_intersection(i1.begin(), i1.end(), i2.begin(), i2.end(), back_inserter(o2))
    o[0] = o2

x = [1, 2, 3]
y = [1, 3, 5]

intersection(&x, &y, &z)
print()
print(z)

运行结果:

[1, 3]

核心诉求

希望直接将交集结果push_back到传入的目标容器指针o指向的容器中,避免临时容器带来的额外拷贝操作。


解决方案

问题根源是back_inserter(o[0])的写法:Cython处理o[0]时,传递给back_inserter的是容器的引用,而std::back_insert_iterator需要的是直接的容器对象(值类型),这导致模板推导错误,生成了不符合标准库要求的std::back_insert_iterator<std::vector<int>&>实例。

有两种修正方式:

方式1:显式获取容器引用

%%cython -a -+

from libcpp.vector cimport vector
from libcpp.algorithm cimport set_intersection
from libcpp.iterator cimport back_inserter

cdef vector[int] x, y, z

cdef intersection(vector[int]* i1, vector[int]* i2, vector[int]* o):
    # 先获取容器的引用,再传入back_inserter
    cdef vector[int]& o_ref = o[0]
    set_intersection(i1.begin(), i1.end(), i2.begin(), i2.end(), back_inserter(o_ref))

x = [1, 2, 3]
y = [1, 3, 5]

intersection(&x, &y, &z)
print(z)

方式2:直接解引用指针

%%cython -a -+

from libcpp.vector cimport vector
from libcpp.algorithm cimport set_intersection
from libcpp.iterator cimport back_inserter

cdef vector[int] x, y, z

cdef intersection(vector[int]* i1, vector[int]* i2, vector[int]* o):
    set_intersection(i1.begin(), i1.end(), i2.begin(), i2.end(), back_inserter(*o))

x = [1, 2, 3]
y = [1, 3, 5]

intersection(&x, &y, &z)
print(z)

两种写法都能让Cython正确推导模板参数,生成标准的std::back_insert_iterator<std::vector<int>>实例,从而直接在目标容器中插入元素,彻底避免额外拷贝。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:06:10