使用Boost序列化库保存加载队列栈时出错,求解决方法
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::queuewithstd::deque: Usepush_back(),pop_front(), andfront()to mirror queue behavior. - Replace
std::stackwithstd::vectororstd::deque: Usepush_back(),pop_back(), andback()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
cis a required member for these adapters). - If you choose Option 2, you won't need any extra code—just adjust your
mystructmembers and update any logic that usesqueue/stackmethods to use the native container equivalents.
内容的提问来源于stack exchange,提问作者samini

