扩展向量迭代器以访问所包含的类/结构的数据成员
因此,我有一个类,它根据附加到字符串中每个字符的元数据进行字符串操作。在内部,我用 std::vector
来表示这一点,其中 CharacterType
包含所讨论的字符等。这种内部表示对我很有用,但在操作结束时,类用户对字符串本身感兴趣。
为了做到这一点,我决定扩展 std::vector
以包含一个 operator*()
方法,该方法返回一个字符而不是 <代码>字符类型。这是代码,它可以在 Windows 7 上的 Visual Studio 2008 中运行。但是它是惯用的 C++ 吗?自 90 年代以来,我没有写过太多 C++,所以如果我在做一些危险和/或邪恶的事情,我会很感激一些关于风格的反馈。 (在下面的代码中,我创建了一个名为 mytype
的简化 CharacterType
结构——实际上,该结构要大一些。)
#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;
}
假设这是良好的样式,是否适合使用 C++ 类型感知方法重载在 myit
中拥有多个 operator*()
方法,以便我可以使用相同的迭代器类来获取不同类型的另一个成员?或者使用模板会更好吗?例如,一项元数据是角色的语言,我希望能够以完全相同的方式提取 std::vector
。想法?
另外,由于返回这些数据的方法不会影响对象的内部表示,因此为了 const 的正确性,我希望能够定义访问器 const
。这可能意味着我需要修改上面的内容以使用 const_iterator 来代替,但我还没有做到这一点。
提前感谢您的风格批评!
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. 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
. Here's the code, it works in Visual Studio 2008 on Windows 7. But is it idiomatic 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. (In the code below I made a simplified CharacterType
structure called mytype
-- in reality the structure is quite a bit bigger.)
#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? 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. 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
. 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.
Thanks for your style critiques in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您不应该派生 std::vector (或其他 STL 容器),因为它的析构函数不是虚拟的,您可能会遇到向量的析构函数未被调用的情况,并且会出现内存泄漏。
You are not supposed to derive std::vector (nor other STL containers), because its destructor is not virtual and you can run into situations the vector's destructor is not called and you get memory leaks.
首先,我也希望在这么长时间的休息之后能够写出如此优秀的C++,如果它发生在我身上的话!
话虽如此,排除从
CharacterType
到char
的简单转换运算符的原因是什么?类似:CharacterType::operator char();
当然,我们都知道运算符重载的问题(但这在两种情况下都不会改变)...
关于您问的其他问题,您无法根据返回类型进行重载,因此如果这就是您的意思,您不可能对不同的返回类型使用不同的operator()。
但正如您提到的,您可以使用模板来实现这一点。
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!
said that, what are the reasons for ruling out a simple conversion operator from your
CharacterType
tochar
? something like: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.
but you could use templates for that, as you mention.
我不相信你可以在同一个类中拥有“多个
operator*()
重载”;想必您希望根据返回类型消除歧义,但 C++ 不会这样做。此外,直接从不相关的迭代器类型派生可能不是一个好主意。为了作为STL迭代器正确运行,迭代器类需要定义许多typedef等。如果您像这样直接继承它们,那么您的所有定义都将毫无意义。有关更多信息,请参阅有关自定义容器和容器的文章。 STL 友好代码的迭代器。
I don't believe that you can have "several
operator*()
overloads" in the same class; presumably you would want to disambiguate based on return-type, but C++ does not do this.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. For more information, see e.g. this article on Custom Containers & Iterators for STL-Friendly Code.
通过从
operator*()
返回除 CharacterType 之外的类型,您将破坏多个迭代器契约。老实说,如果您迫切希望它们可以转换,只需给CharacterType一个operator char()
即可。You're breaking several iterator contracts by returning a type other than CharacterType from
operator*()
. Honestly- just give CharacterType anoperator char()
if you're desperate for them to be convertible.一些不同的人建议我研究转换运算符,我必须承认我完全忘记了。基于转换运算符的解决方案相当干净:
...并且它不需要我担心听起来不祥的事情,例如违反 STL 迭代器契约。另外,似乎(尽管我还没有尝试过)如果我希望能够轻松复制字符串以外的其他内容(我最初问题中的
std::vector想法)我可以通过添加不同的强制转换运算符来轻松扩展它,而迭代器派生技术将需要更多的样板文件,因为 C++ 中没有返回类型多态性,正如一些人向我指出的那样。
非常感谢您的回复,一旦我让代表这样做,我就会投票给你们所有人,以防您想知道为什么我还没有投票。
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:
... and it doesn't involve me worrying about ominous sounding things like violating STL iterator contracts. 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.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.