有没有办法访问STL容器适配器的底层容器?

Ara*_*raK 24 c++ standards stl data-structures

是否有一个标准来访问的底层容器的方式stack,queue,priority_queue

我发现了一个叫方法:_Get_container()VS2008实施stackqueue,但没有一个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_queueVS2008执行.

小智 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)是允许的.


Eva*_*ran 9

我在评论中提到过它,但经过一番思考后似乎是一个很好的解决方案.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 ).stacktypedef