You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Boost序列化库保存加载队列栈时出错,求解决方法

Solution for Boost Serialization with std::queue and std::stack

Hey there! The error you're seeing happens because std::queue and std::stack are container adapters, not native sequence containers—Boost Serialization doesn't include out-of-the-box support for them. Under the hood, these adapters wrap containers like std::deque (the default), but their encapsulated structure means the library can't automatically access and serialize the underlying data.

Why the Error Occurs

When you try to serialize a queue or stack, Boost's serialization code looks for a matching save()/load() function, but can't find one. The error mentions std::deque because that's the default underlying container for both adapters, but the adapter's interface hides it from the serializer.

Fixes to Try

Option 1: Implement Custom Serialization for Adapters

You can manually add serialization support for std::queue and std::stack by accessing their protected underlying container member (c, which is standardized in C++ for these adapters). Here's how:

First, add these template specializations to your code before your mystruct definition:

#include <boost/serialization/serialization.hpp>
#include <queue>
#include <stack>

namespace boost {
namespace serialization {

// Serialize std::queue by accessing its underlying container
template<class Archive, class T, class Container>
void serialize(Archive& ar, std::queue<T, Container>& q, const unsigned int version) {
    // Helper struct to access the protected 'c' member
    struct QueueAccessor : private std::queue<T, Container> {
        static Container& get_container(std::queue<T, Container>& q) {
            return q.c;
        }
    };
    // Serialize the underlying container directly
    Container& underlying = QueueAccessor::get_container(q);
    ar & underlying;
}

// Serialize std::stack the same way
template<class Archive, class T, class Container>
void serialize(Archive& ar, std::stack<T, Container>& s, const unsigned int version) {
    struct StackAccessor : private std::stack<T, Container> {
        static Container& get_container(std::stack<T, Container>& s) {
            return s.c;
        }
    };
    Container& underlying = StackAccessor::get_container(s);
    ar & underlying;
}

} // namespace serialization
} // namespace boost

This code works because the C++ standard mandates that std::queue and std::stack have a protected member c representing their underlying container. The helper struct lets us safely access this member without breaking encapsulation.

Option 2: Replace Adapters with Native Containers

If you don't want to write custom serialization code, swap queue/stack for Boost-supported containers that match your use case:

  • Replace std::queue with std::deque: Use push_back(), pop_front(), and front() to mirror queue behavior.
  • Replace std::stack with std::vector or std::deque: Use push_back(), pop_back(), and back() to mirror stack behavior.

This is the simplest fix if your application logic allows it—Boost already supports all major STL containers natively.

Important Pre-Requisite

Make sure your PKT_UNIT struct has proper serialization support! You need to define a serialize() template for it, like this:

struct PKT_UNIT {
    // Your struct members here
    int id;
    std::string data;

    template<class Archive>
    void serialize(Archive& ar, const unsigned int version) {
        ar & id;
        ar & data;
    }
};

Full Working Example

Here's how your code would look with Option 1 implemented:

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <fstream>
#include <queue>
#include <stack>
#include <iostream>

// PKT_UNIT with serialization
struct PKT_UNIT {
    int value;
    template<class Archive>
    void serialize(Archive& ar, const unsigned int version) {
        ar & value;
    }
};

// Custom serialization for queue/stack (as shown earlier)
namespace boost {
namespace serialization {
template<class Archive, class T, class Container>
void serialize(Archive& ar, std::queue<T, Container>& q, const unsigned int version) {
    struct QueueAccessor : private std::queue<T, Container> {
        static Container& get_container(std::queue<T, Container>& q) {
            return q.c;
        }
    };
    Container& underlying = QueueAccessor::get_container(q);
    ar & underlying;
}

template<class Archive, class T, class Container>
void serialize(Archive& ar, std::stack<T, Container>& s, const unsigned int version) {
    struct StackAccessor : private std::stack<T, Container> {
        static Container& get_container(std::stack<T, Container>& s) {
            return s.c;
        }
    };
    Container& underlying = StackAccessor::get_container(s);
    ar & underlying;
}
} // namespace serialization
} // namespace boost

// Your mystruct with queue/stack members
struct mystruct {
    std::queue<PKT_UNIT> msg_queue;
    std::stack<PKT_UNIT> data_stack;

    void initial() {
        // Populate test data
        msg_queue.push({10});
        msg_queue.push({20});
        data_stack.push({30});
        data_stack.push({40});
    }

    template<class Archive>
    void serialize(Archive& ar, const unsigned int version) {
        ar & msg_queue;
        ar & data_stack;
    }
};

int main() {
    mystruct test;
    test.initial();

    // Save data
    {
        std::ofstream ofs("filename.dat");
        boost::archive::text_oarchive ar(ofs);
        ar & test;
    }

    // Load and verify data
    {
        std::ifstream ifs("filename.dat");
        boost::archive::text_iarchive ar(ifs);
        mystruct restored;
        ar & restored;

        // Print queue contents
        std::cout << "Restored queue values: ";
        while (!restored.msg_queue.empty()) {
            std::cout << restored.msg_queue.front().value << " ";
            restored.msg_queue.pop();
        }
        std::cout << "\n";

        // Print stack contents
        std::cout << "Restored stack values: ";
        while (!restored.data_stack.empty()) {
            std::cout << restored.data_stack.top().value << " ";
            restored.data_stack.pop();
        }
        std::cout << "\n";
    }

    return 0;
}

Final Notes

  • The custom serialization code is portable across all C++ compilers that follow the standard (since c is a required member for these adapters).
  • If you choose Option 2, you won't need any extra code—just adjust your mystruct members and update any logic that uses queue/stack methods to use the native container equivalents.

内容的提问来源于stack exchange,提问作者samini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:39:38