Using the Universal Streaming Service with STL Containers


The USS mechanism also works with STL containers. Because STL containers are template classes, these containers use the same macros discussed in the "Adding Streaming Support to Template Classes" section of this chapter.

Streaming<ToolKit> provides the necessary header macros and the writer/reader functions for streaming all STL containers in Standards<ToolKit>. To use binary streaming on STL containers, provide the source macros for each instance of an STL container. The types you use to instantiate the template must be either primitives or classes that also support binary streaming.

The following sections present an example of streaming for each STL container category.

Binary streaming is not enabled for STL iterators, allocators, or function objects. Consequently, STL iterator objects are not binary streamable. Additionally, containers that use allocators or function objects containing state are not streamable. For more information about STL containers, consult the Standards User Guide and Reference Manual.

Streaming Associative Containers

The following example illustrates how to binary stream an instance of map . This example adds only one source macro for the map instance used.

Example <ospace/stream/examples/stlmap.cpp>
#include <fstream>
#include <map>
#include <string>
#include <ospace/stream.h>
#include <ospace/source.h>
#include <ospace/uss/std/map.h>
#include <ospace/uss/std/string.h>

const int os_map_start_id = os_user_start_id + 1;

// Binary stream macro for the instance of os_map used.

OS_STREAMABLE_0
  (
  ( map< string, string, less< string > >* ),
  os_map_start_id + 1
  )

void
write()
  {
  map< string, string, less< string > > map1;

  // Create a map of acronyms.
  map1[ "FAQ" ] = "Frequently Asked Questions";
  map1[ "OMG" ] = "Object Management Group";
  map1[ "ORB" ] = "Object Request Broker";

  cout << "map1[ \"OMG\" ] = " << map1[ "OMG" ] << endl;
  cout << "map1[ \"ORB\" ] = " << map1[ "ORB" ] << endl;

  // Save the map to a file.
  fstream file( "stlmap.bin", ios::binary | ios::out | ios::trunc );
  os_bstream stream( os_adapter_for( file ) );
  stream << map1;
  cout << "Wrote map to fstream." << endl << endl;
  }

void
read()
  {
  map< string, string, less< string > > map2;
  fstream file( "stlmap.bin", ios::binary | ios::in );
  os_bstream stream( os_adapter_for( file ) );
  stream >> map2;

  cout << "Read map from fstream. " << endl;
  cout << "map2[ \"OMG\" ] = " << map2[ "OMG" ] << endl;
  cout << "map2[ \"ORB\" ] = " << map2[ "ORB" ] << endl;
  }

void
main()
  {
  os_streaming_toolkit initialize;

  write();
  read();
  }

map1[ "OMG" ] = Object Management Group
map1[ "ORB" ] = Object Request Broker
Wrote map to fstream.

Read map from fstream.
map2[ "OMG" ] = Object Management Group
map2[ "ORB" ] = Object Request Broker

Streaming Sequential Containers

The following example illustrates how to binary stream an instance of a list of pointers to a user-defined type X . For simplicity, this example combines the header and source code into one file. Note that the streaming operation performs a deep stream of the list.

<ospace/stream/examples/x.h>
#ifndef X_H
#define X_H

#include <string>
#include <ospace/header.h>

class X
  {
  public:
    X() {};
    X( const string& value ) : value_( value ) {};
    const string& value() const { return value_; };
    void value( const string& value ) { value_ = value; };
    void print( ostream& stream ) const { stream << value_ << endl; };

  private:
    string value_;
  };


// Forward declare writer and reader functions.
void os_write( os_bstream&, const X& );
void os_read( os_bstream&, X& );

// Header macros.
OS_CLASS( X )
OS_STREAM_OPERATORS( X )
#endif
<ospace/stream/examples/x.cpp>
#include "x.h"
#include <fstream>
#include <ospace/source.h>

// Source macro.
OS_STREAMABLE_0( (X*), os_use_name_as_id )

// Streaming functions for X.
void
os_write( os_bstream& stream, const X& object )
  {
  stream << object.value();
  }

void
os_read( os_bstream& stream, X& object )
  {
  string value;
  stream >> value;
  object.value( value );
  }

Example <ospace/stream/examples/stllist.cpp>
#include "x.h"
#include <list>
#include <string>
#include <fstream>
#include <ospace/stream.h>
#include <ospace/source.h>
#include <ospace/uss/std/list.h>
#include <ospace/uss/std/string.h>

const int os_list_start_id = os_user_start_id + 100;
OS_STREAMABLE_0(( list< X* >* ), os_list_start_id + 1 )

// Print the contents of list.

void
print( const list< X* >& list_ )
  {
  list< X* >::const_iterator i;

  for ( i = list_.begin(); i != list_.end(); i++ )
    cout << (*i)->value() << endl;
  }

void
write()
  {
  // Create a list of pointer to X objects.
  list< X* > list1;

  list1.push_back( new X( "abc" ) );
  list1.push_back( new X( "bcd" ) );
  list1.push_back( new X( "cde" ) );
  list1.push_back( new X( "def" ) );

  fstream file( "stllist.bin", ios::binary | ios::out | ios::trunc );
  os_bstream stream( os_adapter_for( file ) );
  stream << list1;

  cout << "Wrote to the stream : " << endl;
  print( list1 );
  cout << endl;
  }

void
read()
  {
  // Restore the list of X objects back from the file
  os_list< X* > list2;
  fstream file( "stllist.bin", ios::binary | ios::in );
  os_bstream stream( os_adapter_for( file ) );
  stream >> list2;

  cout << "Read from the stream : " << endl;
  print( list2 );
  }

void
main()
  {
  os_streaming_toolkit initialize;

  write();
  read();
  }

Wrote to the stream :
abc
bcd
cde
def

Read from the stream :
abc
bcd
cde
def

Streaming Container Adapters

Because container adapters work on the actual containers, every instance of the container adapter used generates an instance of the actual container. Therefore, provide a separate binary stream source macro for the instance of the actual container generated by the container adapter.

The following example illustrates how to stream an instance of stack . Because stack uses a vector , an instance of stack generates an instance of vector . Therefore, a binary stream macro is provided for stack and vector .

Example <ospace/stream/examples/stlstack.cpp>
#include <fstream>
#include <stack>
#include <vector>
#include <ospace/stream.h>
#include <ospace/source.h>
#include <ospace/uss/std/stack.h>
#include <ospace/uss/std/vector.h>

const int os_stack_start_id = os_user_start_id + 1;
const int os_vector_start_id = os_user_start_id + 100;

// Binary stream macro for the instance of stack used.

OS_STREAMABLE_0
  (
  ( stack< int, vector< int > >* ),
  os_stack_start_id + 1
  )

// Binary stream macro for the instance of vector used by
// stack implicitly.

OS_STREAMABLE_0
  (
  ( vector< int >* ),
  os_vector_start_id + 1
  )

// Print the contents of the stack.

void
print( const stack< int, vector< int > >& s )
  {
  stack< int, vector< int > > temp( s );

  while ( !temp.empty() )
    {
    cout << temp.top() << endl;
    temp.pop();
    }
  }

void
write()
  {
  // Create a stack of ints.
  stack< int, vector< int > > stack1;
  stack1.push( 1001 );
  stack1.push( 1002 );
  stack1.push( 1003 );

  // Save the stack to a file.
  fstream file( "stlstack.bin", ios::binary | ios::out | ios::trunc );
  os_bstream stream( os_adapter_for( file ) );
  stream << stack1;

  cout << "Wrote to the stream : " << endl;
  print( stack1 );
  cout << endl;
  }

void
read()
  {
  // Restore the stack of ints back from the file
  stack< int, vector< int > > stack2;
  fstream file( "stlstack.bin", ios::binary | ios::in );
  os_bstream stream( os_adapter_for( file ) );
  stream >> stack2;

  cout << "Read from the stream : " << endl;
  print( stack2 );
  }

void
main()
  {
  os_streaming_toolkit initialize;

  write();
  read();
  }

Wrote to the stream :
1003
1002
1001

Read from the stream :
1003
1002
1001

Copyright©1994-2026 Recursion Software LLC
All Rights Reserved - For use by licensed users only.