#ifndef BOOST_ARCHIVE_ARRAY_OARCHIVE_HPP

#define BOOST_ARCHIVE_ARRAY_OARCHIVE_HPP



// (C) Copyright 2005 Matthias Troyer and Dave Abrahams

// Use, modification and distribution is subject to the Boost Software

// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at

// http://www.boost.org/LICENSE_1_0.txt)





#include <boost/archive/basic_archive.hpp>

#include <boost/archive/detail/common_oarchive.hpp>

#include <boost/serialization/array.hpp>

#include <boost/serialization/collection_size_type.hpp>

#include <boost/serialization/nvp.hpp>

#include <boost/serialization/detail/get_data.hpp>

#include <boost/type_traits/remove_const.hpp>

#include <boost/type_traits/is_same.hpp>

#include <boost/mpl/apply.hpp>

#include <boost/mpl/bool.hpp>

#include <boost/pfto.hpp>



namespace boost { namespace archive { namespace array {



  // To conveniently array-optimize an output archive X:

  //

  //   * Derive it from oarchive<X, Impl>, where Impl is an 

  //     archive implementation base class from 

  //     Boost.Serialization

  //

  //   * add a member function template that implements the

  //     procedure for serializing arrays of T (for appropriate T)

  //

  //       template <class T>

  //       save_array(serialization::array<T> const &, unsigned int)

  //

  //   * add a unary MPL lambda expression member called

  //     use_array_optimization whose result is convertible to

  //     mpl::true_ iff array elements of type T can be serialized

  //     with the load_array member function, and to mpl::false_ if

  //     the unoptimized procedure must be used. 



template <class Archive>

class oarchive

 : public archive::detail::common_oarchive<Archive>

{

  typedef archive::detail::common_oarchive<Archive> Base;

public:



  oarchive(unsigned int flags)

   : archive::detail::common_oarchive<Archive>(flags)

  {}

  

  // save_override for std::vector and serialization::array dispatches to 

  // save_optimized with an additional argument.

  // 

  // If that argument is of type mpl::true_, an optimized serialization is provided

  // If it is false, we just forward to the default serialization in the base class

  

  //the default version dispatches to the base class

  template<class T>

  void save_optimized(T const &t, unsigned int version, mpl::false_)

  {

    Base::save_override(t, version);

  }





  // the optimized implementation for vector uses serialization::array

//  template<class ValueType, class Allocator>

//  void save_optimized(

//    const std::vector<ValueType, Allocator> &t, unsigned int, mpl::true_)

//  {

//    const serialization::collection_size_type count(t.size());

//    * this->This() << BOOST_SERIALIZATION_NVP(count);

//    if (!t.empty())

//      * this->This() << serialization::make_array(serialization::detail::get_data(t),t.size());

//  }



  // the optimized implementation for serialization::array uses save_array

  template<class ValueType>

  void save_optimized(

    const serialization::array<ValueType> &t, unsigned int version, mpl::true_)

  {

    this->This()->save_array(t,version);

  }





  // to save a vector:

  // if the value type is trivially constructable or an optimized array save exists, 

  // then we can use the optimized version



//  template<class ValueType, class Allocator>

//  void save_override(std::vector<ValueType,Allocator> const &x, unsigned int version)

//  {

//    typedef BOOST_DEDUCED_TYPENAME remove_const<ValueType>::type value_type;

//    typedef typename mpl::and_<

//      mpl::not_<is_same<value_type,bool> >,

//      mpl::apply1<

//        BOOST_DEDUCED_TYPENAME Archive::use_array_optimization

//      , value_type>

//    >::type use_optimized;

//    save_optimized(x,version,use_optimized() );   

//  }



  

  

  // dispatch saving of arrays to the optimized version where supported

  template<class ValueType>

  void save_override(serialization::array<ValueType> const& x, unsigned int version)

  {

    typedef typename mpl::apply1<

        BOOST_DEDUCED_TYPENAME Archive::use_array_optimization

      , BOOST_DEDUCED_TYPENAME remove_const<ValueType>::type

    >::type use_optimized;

    save_optimized(x,version,use_optimized());

  }



  // Load everything else in the usual way, forwarding on to the

  // Base class

  template<class T>

  void save_override(T const& x, unsigned BOOST_PFTO int version)

  {

    Base::save_override(x, static_cast<unsigned int>(version));

  }

};



} } } // end namespace boost::archive::array





#endif // BOOST_ARCHIVE_ARRAY_OARCHIVE_HPP



