有没有办法访问STL容器适配器的底层容器?
是否有一种标准方式来访问stack
、queue
、priority_queue ?
我在stack
和queue
的VS2008
实现中发现了一种名为:_Get_container()
的方法,但没有人<代码>优先级队列! 我认为无论如何这都不标准。
另外,我知道这是一个愚蠢的问题! 在哪里可以找到标准库的官方文档?
只是为了澄清,我并不想搞乱底层容器。 我想做的就是这样:
template <class Container>
std::ostream& printOneValueContainer(std::ostream& outputstream, Container& container)
{
Container::const_iterator beg = container.begin();
outputstream << "[";
while(beg != container.end())
{
outputstream << " " << *beg++;
}
outputstream << " ]";
return outputstream;
}
// stack, queue
template
< class Type
, template<class Type, class Container = std::deque<Type> > class Adapter
>
std::ostream& operator<<(std::ostream& outputstream, const Adapter<Type>& adapter)
{
return printOneValueContainer(outputstream, adapter._Get_container());
}
.
.
.
std::stack<int> iStack;
.
.
std::cout << iStack << std::endl;
我希望你看到 _Get_container()
不是标准的,并且 VS2008
中没有 priority_queue
。代码> 实现。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我在网络上的某个地方发现了以下解决方案,并且我正在我的项目中使用它:
玩得开心:)。
I spotted the following solution somewhere on the web and I'm using it in my projects:
Have fun :).
基于接受的答案,一种更通用的方法:
正如我从这个答案,
.*&
实际上是两个运算符,其中&hack::c
产生的指针(其类型为ADAPTER::container_type ADAPTER::*
)是用于检索底层容器本身的目标或.*
运算符。hack
可以访问受保护的成员,但获得指针后,保护就会丢失。 所以a.*(&hack::c)
是允许的。Based on the accepted answer, a more general approach:
As I learned from this answer,
.*&
is actually two operators, where the pointer resulting from&hack::c
(which has typeADAPTER::container_type ADAPTER::*
) is the target or the.*
operator to retrieve the underlying container itself.hack
has access to the protected member, but after the pointer is obtained, protections are lost. Soa.*(&hack::c)
is allowed.我在评论中提到过,但经过一番思考,这似乎是一个不错的解决方案。
queue
/stack
/priority_queue
(即所有适配器类)都有一个protected
成员c
是底层容器(请参阅 ISO/IEC 14882:2003 第 23.2.2.4 节),因此如果您从其中任何一个继承,则可以直接访问它。我知道典型的智慧是由于非虚拟 dtor 而不要从 STL 容器继承,但这种情况是一个例外。 目标不是使功能过载,而是对适配器的接口进行较小的扩展。 下面是添加访问底层容器的能力的示例。
不幸的是,您必须诉诸类型双关来“升级”现有的 std::queue 。 * 到
Adapter; > *。 从技术上讲,这可能会很好地工作......但我建议不要这样做:
所以我建议使用 typedef 来轻松在两者之间进行交换。 (另请注意,在我的示例中,由于
typedef
的自由使用,您只需更改 1 行即可将其从queue
更改为stack
>s)。I mentioned it in a comment, but after some thinking, it seems to be an OK solution.
queue
/stack
/priority_queue
(that is, all of the adapter classes) all have aprotected
memberc
which is the underlying container (see ISO/IEC 14882:2003 section 23.2.2.4), so if you inherit from any of these, you can access it directly.I know the typical wisdom is to not inherit from STL containers due to non-virtual dtors, but this case is an exception. The goal is not to overload functionality, but to make minor extensions to the interface of the adapter. Here is an example of adding the ability to access the underlying container.
Unfortunately, you'll have to resort to type-punning to "upgrade" an existing
std::queue<int> *
to aAdapter<std::queue<int> > *
. Technically, this would likely work fine... but I recommend against it:So I would recommend using typedefs to make it easy to swap between the two. (Also notice in my example that you only need to change 1 line to change it from a
queue
to astack
because of the liberal use oftypedef
s).不,没有标准的方法可以做到这一点。 至于访问该标准,它在网络上不可用,您必须购买副本! 但有各种草稿副本
可在此处获取。
No, there is no standard way of doing that. As for access to the standard, it is not available onn the web, you have to buy a copy! However, there are various copies of drafts
available here.
我相信,这个 SGI 页面是最“官方”的在线文档。
您无法直接访问底层容器的原因是适配器更改了使用模式,并且使底层容器的方法可用将违反该新的使用模式。 例如:
如果您想绕过此设计功能,您可以执行以下操作:
This SGI page is the most "official" documentation available online, I believe.
The reason that you can't get direct access to the underlying container is that the adapter changes the usage pattern, and having the methods of the underlying container available would violate that new usage pattern. For example:
If you want to get around this design feature, you can do something like:
作为一般规则,任何以下划线开头的标识符都是供应商特定的扩展或实现细节。 所以
_Get_container()
只是微软的一个补充,因为它简化了他们的实现。 它不打算被使用。至于在哪里可以找到文档,它分为几个部分。
权威来源当然是语言标准。 正如尼尔·巴特沃斯所说,网上有免费的草稿副本(仍然非常有用。与最终版本的差异非常小)。 或者,您可以购买副本。 它应该可以从您所在国家代表 ISO 的任何组织获得(也可能从无数其他来源获得)。 您要查找的文档是
ISO/IEC 14882:2003 编程语言 C++
。 (14882是标准编号。2003年是最后一次修订的年份。如果你遇到过1998年的版本,也可以使用它。两者之间的差异确实小得离谱,基本上只是一些澄清。可能最好远离 C++0x 的草案,因为那里的更改要广泛得多)除此之外,标准库的每个实现都需要记录大量细节(实现定义的行为、标准中未指定,而是由库实现者决定)。 此外,他们中的大多数还提供了整个库的详细文档。
Microsoft 在 MSDN 上提供了详细文档。 该文档尊重标准,并清楚地标记所有非标准扩展,以便您知道哪个是哪个。
SGI 也有在线文档(尽管它较旧,并且在某些情况下并不完全准确) )。
IBM 在其网站上提供了类似的文档,我相信 GCC 也有。
As a general rule, any identifier that starts with an underscore is a vendor-specific extension or an implementation detail. So
_Get_container()
is just an addition made by Microsoft because it simplified their implementation. It is not intended to be used.As for where to find the documentation, it's split into several parts.
The authoritative source is, of course, the language standard. As Neil Butterworth said, there are draft copies available for free online (which are still very useful. The differences from those to the final version are really minimal). Alternatively, you can buy a copy. It should be available from whichever organization represents ISO in your country (and probably from a bajillion other sources as well). The document you're looking for is
ISO/IEC 14882:2003 Programming Language C++
. (14882 is the standard number. 2003 is the year of the last revision. If you come across the 1998 version, you can use that too. The differences are really ridiculously small between the two, and basically just amounts to a few clarifications. It's probably best to stay away from the drafts for C++0x, as the changes there are far more extensive)Apart from that, every implementation of the standard library is required to document a large number of details (implementation-defined behavior, things which are not specified in the standard, but is left up to the library implementer). And in addition, most of them also put up a detailed documentation of the entire library as well.
Microsoft has detailed documentation available on MSDN. The documentation respects the standard, and clearly marks all nonstandard extensions so you know which is which.
SGI also has the documentation online (although it is older and in some cases, not entirely accurate).
IBM has similar documentation available on their website, and I believe GCC does too.
我当然希望没有办法访问优先级队列的底层容器。 如果可以的话,您可能会弄乱优先级队列的内部堆结构。 无论如何,这些适配器的要点是它们仅为您提供堆栈或队列的最小接口,并抽象出所有其他内容。 因此,如果您需要使用任何其他功能,您应该直接使用原始容器。
至于STL的文档,你可以在这里查看SGI的STL文档。 SGI 的 STL 与 C++ 标准中的 STL 之间存在一些差异,但它们大多在该网站上注明。 此外,cppreference.com 是 C++ 库的 wiki 文档,该文档正在变得更加完整。
I certainly hope there isn't a way to access the underlying container of a priority queue. If you could then you could mess up the internal heap structure of the priority queue. In any case the point of those adaptors is that they only present you with the minimal interface of the stack or queue, and abstract out all the other things. So if you needed to use any other features, you should have used the original container directly.
As for documentation of the STL, you can look at the documentation of SGI's STL here. There are a few differences between SGI's STL and the one in the C++ standard, but they are mostly noted on that site. Also, cppreference.com is a wiki documentation of the C++ library that is becoming more complete.
您可以编写一个子类来检索成员变量 c。
请参阅 libstdc++ 的评论。
You can write a subclass to retrieve the member variable c.
See this comment from libstdc++.
这应该适用于最新的 ISO 编译器:
用法:
This should work on recent ISO compilers:
Usage:
在哪里可以找到标准库的官方文档?
C++ 标准有精装本,ISBN 0470846747。
标准草案以 PDF 形式广泛存在,但您必须小心地将它们与官方版本(C++98、03、11 或 14)相匹配。 当前的草案超出了 C++14 标准。
where can I find official documentation of the standard library?
The C++ standard is available in hardcover, ISBN 0470846747.
Drafts of Standard are widely available in PDF form, but you'll have to be careful to match them with the official versions (C++98,03,11 or 14). The current drafts exceed the C++14 standard.