简体   繁体   English

扩展向量迭代器以访问所包含的类/结构的数据成员

[英]Extending a vector iterator to access data members of the contained class/structure

So, I have a class that does string manipulation based on metadata attached to each character in the string. 因此,我有一个基于附加到字符串中每个字符的元数据进行字符串操作的类。 Internally, I represent this with a std::vector<CharacterType> where CharacterType contains, among other things, the character in question. 在内部,我用std::vector<CharacterType>表示该std::vector<CharacterType> ,其中CharacterType除其他外还包含所讨论的字符。 This internal representation is useful to me, but at the end of the manipulation(s) the class user is interested in the string itself. 这种内部表示对我很有用,但是在操作结束时,类用户对字符串本身感兴趣。

In order to do this, I decided to extend std::vector<CharacterType>::iterator to include an operator*() method that returns a character rather than a CharacterType . 为了做到这一点,我决定扩展std::vector<CharacterType>::iterator以包括一个operator*()方法,该方法返回一个字符而不是CharacterType Here's the code, it works in Visual Studio 2008 on Windows 7. But is it idiomatic C++? 这是代码,它可以在Windows 7的Visual Studio 2008中使用。但是它是惯用的C ++吗? I haven't written much C++ since the 90s, so I'd appreciate some feedback on the style or if I'm doing something dangerous and/or evil. 自90年代以来,我没有写太多C ++,因此,我希望能得到一些有关样式的反馈,或者如果我在做危险和/或邪恶的事情。 (In the code below I made a simplified CharacterType structure called mytype -- in reality the structure is quite a bit bigger.) (在下面的代码中,我做了一个简化的CharacterType结构,称为mytype -实际上,该结构要大得多。)

#include <iostream>
#include <vector>
#include <string>

struct mytype {
    char c;
};

class myit : public std::vector<mytype>::iterator {
public:
    inline myit(std::vector<mytype>::iterator const &c)
        : std::vector<mytype>::iterator(c) {}
    char operator*() {
        const mytype &p =
            std::vector<mytype>::iterator::operator*();
        return p.c;
    }

    // Added these in a later edit, after thinking about a comment below
    typedef char value_type;
    typedef char *pointer;
    typedef char &reference;

private:
};

int
main()
{
    mytype test[] = { {'a'}, {'b'}, {'c'}, {'d'} };
    std::vector<mytype> vec(&test[0], &test[4]);
    myit i(vec.begin()), e(vec.end());
    std::string str(i, e);

    std::cout << str << std::endl;
    return 0;
}

Assuming this is good style, is it appropriate to use C++ type-aware method overloading to have several operator*() methods in myit so that I can use the same iterator class to get another member of a different type? 假设这是一种好的样式,是否适合使用C ++类型感知方法重载在myit具有多个operator*()方法,以便我可以使用相同的迭代器类来获取另一种不同类型的成员? Or would it be better to use a template? 还是使用模板会更好? For example, one piece of metadata is the character's language, and I would like to be able to extract a std::vector<LanguageType> in exactly the same way. 例如,一个元数据是角色的语言,我希望能够以完全相同的方式提取std::vector<LanguageType> Thoughts? 有什么想法吗?

Also, since the methods that return these data don't affect the object's internal representation, in the interest of const correctness I would like to be able to define the accessors const . 另外,由于返回这些数据的方法不会影响对象的内部表示,因此,为了保证const正确性,我希望能够定义访问器const This probably means that I'd need to modify the above to use a const_iterator instead, but I haven't gotten to that yet. 这可能意味着我需要修改上面的内容以改为使用const_iterator ,但是我还没有做到这一点。

Thanks for your style critiques in advance! 预先感谢您对风格的批评!

first of all, I would also like to be able to write so good C++ after such a long break, if it should ever happen to me! 首先,如果经历了那么长的休息,我还希望能够编写出如此出色的C ++!

said that, what are the reasons for ruling out a simple conversion operator from your CharacterType to char ? 说,排除从您的CharacterTypechar的简单转换运算符的原因是什么? something like: CharacterType::operator char(); 像这样: CharacterType::operator char();

of course, we all know the problems with operator overloading (but that would not change in the two cases)... 当然,我们都知道运算符重载的问题(但这在两种情况下不会改变)...

about other things you ask, you cannot overload based on the return type, so you could not possibly have different operator()s for different return types, if that's what you mean. 关于您要问的其他事情,您不能基于返回类型进行重载,因此,如果您要说的是,那么您就不可能针对不同的返回类型使用不同的operator()。

but you could use templates for that, as you mention. 但是您可以使用模板(如前所述)。

您不应该派生std :: vector(也不派生其他STL容器),因为它的析构函数不是虚拟的,并且您可能会遇到不调用vector的析构函数的情况,并且会发生内存泄漏。

I don't believe that you can have "several operator*() overloads" in the same class; 我不认为您可以在同一个类中出现“多个operator*()重载”。 presumably you would want to disambiguate based on return-type, but C++ does not do this. 大概您希望根据return-type进行歧义处理,但是C ++不会这样做。

Also, directly deriving from an unrelated iterator type may not be a great idea. 同样,直接从不相关的迭代器类型派生可能也不是一个好主意。 In order to operate correctly as an STL iterator, an iterator class needs to define a number of typedefs, etc. None of yours will be meaningful if you directly inherit them like this. 为了正确地作为STL迭代器运行,迭代器类需要定义许多typedef,等等。如果您直接像这样继承它们,那么您的任何一个都不有意义。 For more information, see eg this article on Custom Containers & Iterators for STL-Friendly Code . 有关更多信息,请参见例如有关STL友好代码的自定义容器和迭代器的文章。

You're breaking several iterator contracts by returning a type other than CharacterType from operator*() . 您通过从operator*()返回除CharacterType以外的类型来破坏多个迭代器协定。 Honestly- just give CharacterType an operator char() if you're desperate for them to be convertible. 老实说-如果您迫切希望CharacterType可转换,请给CharacterType一个operator char()

A few different people suggested that I look into conversion operators, which I must admit I totally forgot about. 一些不同的人建议我研究转换运算符,我必须承认我完全忘记了这一点。 A conversion operator based solution is considerably cleaner: 基于转换运算符的解决方案更加简洁:

#include <iostream>
#include <vector>
#include <string>

struct mytype {
    char c;
    inline operator char () { return c; }
};

int
main()
{
    mytype test[] = { {'a'}, {'b'}, {'c'}, {'d'} };
    std::vector<mytype> vec(&test[0], &test[4]);
    std::string str(vec.begin(), vec.end());

    std::cout << str << std::endl;
    return 0;
}

... and it doesn't involve me worrying about ominous sounding things like violating STL iterator contracts. ...并不需要担心担心诸如违反STL迭代器合同之类的不祥之兆。 Plus, it seems (although I haven't tried it yet) that if I want to be able to easily copy something other than the string (the std::vector<LanguageType> idea in my original question) I can extend this easily by just adding a different cast operator, whereas the iterator derivation technique would have required much more boilerplate, since there is no return type polymorphism in C++, as several people pointed out to me. 另外,似乎(尽管我还没有尝试过)如果我希望能够轻松复制字符串以外的其他东西(我的原始问题中的std::vector<LanguageType>想法),我可以通过以下方式轻松扩展只是增加了一个不同的强制转换运算符,而迭代器派生技术则需要更多样板,因为C ++中没有返回类型的多态性,正如一些人指出的那样。

Thanks a lot for your responses, once I get the rep to do it I will upvote you all, in case you're wondering why I haven't yet. 非常感谢您的回复,一旦我得到代表的帮助,我就会全民投票,以防万一您想知道为什么我还没有。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM