如何在不使用索引的情况下创建目标语言不可知的迭代SWIG C++对象

2024-04-26 17:30:42 发布

您现在位置:Python中文网/ 问答频道 /正文

<>我有点喜欢WIG和C++,所以这可能是显而易见的,但我似乎无法理解。我有一个C++集合对象(在MWE,A^ {CD1}}),C++中的索引是由^ {< CD2> },但在对象上迭代。这在C++中使用了一个基于范围的循环,其中实现了{{CD3}}和^ {CD4}}。你知道吗

这里有一个中景:

食品储藏室

%module(directors="1") my_collection
%include "stdint.i"
%include "std_string.i"
%include "std_shared_ptr.i"
%include "std_vector.i"
%{
#include "my_collection.cpp"
%}
%nodefaultctor;
%shared_ptr(Food);
%include "my_collection.cpp"

餐具室.cpp

#pragma once

#include <string>
#include <vector>
#include <map>
#include <memory>
#include <sstream>

#ifdef SWIG

%define TO_STRING()
    %extend {
        %feature("python:slot", "tp_repr", functype="reprfunc") to_string;
    }
    std::string to_string()
%enddef

%define SUBSCRIPT(return_type, subscript_type)
    %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__;
    %extend {
        return_type __getitem__(subscript_type key) {
            return (*($self))[key];
        };
    };
    return_type operator[](subscript_type key)
%enddef

#else

#define TO_STRING() \
        std::string to_string()

#define SUBSCRIPT(return_type, subscript_type) \
        return_type operator[](subscript_type key)

#endif


class Food {
public:

    std::string name;

    Food(std::string name) {
        this->name = name;
    };

    TO_STRING() {
        std::ostringstream stream;
        stream << "<Food " << this->name << ">";
        return stream.str();
    };

};

class Pantry {
private:

    // _foods is not grammatically correct
    std::map<std::string, std::shared_ptr<Food>> _food_map;
    std::vector<std::shared_ptr<Food>> _food_vec;

public:
    Pantry() {
    };

    std::shared_ptr<Food> add(std::string name) {
        auto food = std::shared_ptr<Food>(new Food(name));
        this->_food_map[food->name] = food;
        this->_food_vec.push_back(food); // p.s., how do I prevent making a copy?
        return food;
    };

    SUBSCRIPT(std::shared_ptr<Food>, std::string) {
        return this->_food_map.at(key);
    };

    TO_STRING() {
        return "<Pantry>";
    };

    std::vector<std::shared_ptr<Food>>::const_iterator begin() {
        return this->_food_vec.begin();
    };

    std::vector<std::shared_ptr<Food>>::const_iterator end() {
        return this->_food_vec.end();
    };

    size_t size() {
        return this->_food_vec.size();
    };

};

我还编写了一个简短的Python脚本:

import pantry
pant = mc.Pantry()
print(pant.add('Bacon'))
print(pant.add('Cheese'))
print('subscript[Bacon]: {}'.format(pant['Bacon']))
for food in pant:
    print('iter: ... {}'.format(food))

然后,根据-builtin标志是否传递给SWIG,我得到错误:

  • 没有-builtinTypeError: in method 'Pantry___getitem__', argument 2 of type 'std::string'--这是有意义的,因为我选择了按字符串索引
  • 对于-builtinTypeError: 'my_collection.Pantry' object is not iterable--我认为这是由于SWIG没有隐式地创建我没有声明的方法造成的,这在本例中似乎是正确的。你知道吗

如何迭代集合内容而不显式调用方法?我意识到我可以将_food_vec公开并迭代,但是我的实际代码更复杂,我不想这样做。同样,我可以实现一些其他的.iterate()方法,但是我已经完成了begin()end()的工作。你知道吗

编辑:我可以实现什么样的目标语言不可知方法,类似于我为TO_STRING()SUBSCRIPT创建的宏,以及添加到接口文件的正确模板是什么(类似于%template(FoodIterator) std::vector<Food>::iterator;)?你知道吗


Tags: namestringreturnincludefoodtypethisshared
1条回答
网友
1楼 · 发布于 2024-04-26 17:30:42

您有two options来实现iterable接口:

  1. 实现__iter__(),它返回一个具有next()的对象实例。你知道吗
  2. 实现接受integers or slice objects__getitem__()。你知道吗

我想这应该可以解释这两个错误,同时也可以提供一个如何修复的线索。你知道吗

相关问题 更多 >