Ara*_*raK 24 c++ standards stl data-structures
是否有一个标准来访问的底层容器的方式stack
,queue
,priority_queue
?
我发现了一个叫方法:_Get_container()
在VS2008
实施stack
和queue
,但没有一个priority_queue
!我认为它不是标准的.
另外,我知道这是一个愚蠢的问题!我在哪里可以找到标准库的官方文档?
仅仅为了澄清,我并没有试图弄乱底层容器.我试图做的就是:
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;
Run Code Online (Sandbox Code Playgroud)
我希望你看到的_Get_container()
不规范,也没有一个priority_queue
在VS2008
执行.
小智 20
我在网络上的某个地方发现了以下解决方案,我在我的项目中使用它:
template <class T, class S, class C>
S& Container(priority_queue<T, S, C>& q) {
struct HackedQueue : private priority_queue<T, S, C> {
static S& Container(priority_queue<T, S, C>& q) {
return q.*&HackedQueue::c;
}
};
return HackedQueue::Container(q);
}
int main()
{
priority_queue<SomeClass> pq;
vector<SomeClass> &tasks = Container(pq);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
玩得开心 :).
jxh*_*jxh 10
基于接受的答案,更通用的方法:
template <class ADAPTER>
typename ADAPTER::container_type & get_container (ADAPTER &a)
{
struct hack : ADAPTER {
static typename ADAPTER::container_type & get (ADAPTER &a) {
return a.*&hack::c;
}
};
return hack::get(a);
}
Run Code Online (Sandbox Code Playgroud)
正如我从这个答案中学到的,.*&
实际上是两个运算符,其中&hack::c
(由具有类型ADAPTER::container_type ADAPTER::*
)产生的指针是目标或.*
运算符来检索底层容器本身.hack
可以访问受保护的成员,但在获得指针后,保护将丢失.所以a.*(&hack::c)
是允许的.
我在评论中提到过它,但经过一番思考后似乎是一个很好的解决方案.queue
/ stack
/ priority_queue
(即所有适配器类)都有一个protected
成员c
,它是底层容器(参见ISO/IEC 14882:2003第23.2.2.4节),因此如果从其中任何一个继承,您可以直接访问它.
我知道典型的智慧是不会因非虚拟dtors而从STL容器继承,但这种情况是个例外.目标不是重载功能,而是对适配器的接口进行小的扩展.以下是添加访问基础容器的功能的示例.
#include <queue>
#include <iostream>
template <class Container>
class Adapter : public Container {
public:
typedef typename Container::container_type container_type;
container_type &get_container() { return this->c; }
};
int main() {
typedef std::queue<int> C;
typedef Adapter<C> Container;
Container adapter;
for(int i = 0; i < 10; ++i) {
adapter.push(i);
}
Container::container_type &c = adapter.get_container();
for(Container::container_type::iterator it = c.begin(); it != c.end(); ++it) {
std::cout << *it << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,你不得不求助于类型惩罚来将现有的"升级" std::queue<int> *
改为Adapter<std::queue<int> > *
没有类型的惩罚.从技术上讲,这可能会很好......但我建议不要这样做:
typedef std::stack<int> C;
typedef Adapter<C> Container;
C stack;
// put stuff in stack
Container *adapter = reinterpret_cast<Container *>(&stack);
Container::container_type &c = adapter->get_container();
// from here, same as above
Run Code Online (Sandbox Code Playgroud)
因此,我建议使用typedef,以便在两者之间轻松切换.(另请注意,在我的例子中,由于自由使用s ,你只需要改变1行就可以将它从a queue
改为a ).stack
typedef