首页 > 解决方案 > 我想在cpp中实现python列表,但卡在重载下标运算符[]和逗号,

问题描述

我想在cpp中实现puthon列表,bug没有找到实现pyton切片运算符的方法,例如:

list[3:7]   // sublist including item 3 included to item 7 excluded

由于冒号不是 cpp 中的运算符,我们不能重载它。所以我改变了我的实现以使用可重载的逗号,例如list[3,7]. 我想我首先需要重载逗号运算符,然后重载[ ]运算符

[ ]但是在使用 2 个整数重载时出现错误:

Error is : operator[](int, int) must have exactly one argument   

请帮我解决问题。

标签: c++operator-overloadingslicecomma-operatorsubscript-operator

解决方案


C++ 标准对以下内容施加了限制operator[]

[over.sub]: operator[]应该是一个只有一个参数的非静态成员函数。它实现了下标语法

(...) 下标表达式x[y]被解释为x.operator[](y)(...)

但单个参数不需要是标量。例如:

struct mylist {
    vector<int> oops { 3,5, 7, 9}; 
    int& operator[] (size_t i) { 
        cout << "indexing overload"<<endl; 
        return oops[i]; 
    }
    mylist operator[] (pair<int, int>p) { 
        cout << "slicing overload from "<<p.first<<" to "<<p.second<<endl; 
        return mylist();    // just for proof of concept  
    }
};

然后,您可以按预期使用此列表:

mylist l; 
cout<< l[2] <<endl;  // (1) traditional indexing 
l[make_pair(3,5)];   // (2) will invoke the slice version 
l[{4,8}];            // (3) slice version as well

在线演示

但是,C++ 不是 python,所以你的代码的读者会对 (2) 和 (3) 的语法感到非常困惑。此外,我不是 python 专家,但我知道切片运算符可能比这更棘手,因为可能存在启动、停止和步进,并且任何这些组件都可能丢失。

所以我建议不要使用一对作为参数,而是创建自己的切片运算符参数。然后,您可以处理不同的构造函数和默认参数。它可能看起来像:

l[myslice(3, 5)];     // myslice is a class 
l[myslice(3, 4, 2)]; 
l[mysliceto(5)];      // mysliceto could be a function returning a myslice
                      // that is constructed using a default value for start 

但是由于这仍然是一个非常不寻常的索引方案,考虑到最小惊讶的原则,我强烈建议采用 C++ 通常的做法并简单地定义正确的成员函数,例如 `

l.slice(3,5); 

这将是自记录的,毫不奇怪,并且易于消化,因为它接近于众所周知的语义string::substr()


推荐阅读