os/ossrv/stdcpp/tsrc/Boost_test/ptr_container/src/tut1.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
//
sl@0
     2
// Boost.Pointer Container
sl@0
     3
//
sl@0
     4
//  Copyright Thorsten Ottosen 2003-2005. Use, modification and
sl@0
     5
//  distribution is subject to the Boost Software License, Version
sl@0
     6
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
sl@0
     7
//  http://www.boost.org/LICENSE_1_0.txt)
sl@0
     8
//
sl@0
     9
// For more information, see http://www.boost.org/libs/ptr_container/
sl@0
    10
//
sl@0
    11
sl@0
    12
//
sl@0
    13
// This example is intended to get you started.
sl@0
    14
// Notice how the smart container
sl@0
    15
//
sl@0
    16
// 1. takes ownership of objects
sl@0
    17
// 2. transfers ownership
sl@0
    18
// 3. applies indirection to iterators 
sl@0
    19
// 4. clones objects from other smart containers
sl@0
    20
// 
sl@0
    21
sl@0
    22
//
sl@0
    23
// First we select which container to use.
sl@0
    24
//
sl@0
    25
#include <boost/ptr_container/ptr_deque.hpp>
sl@0
    26
sl@0
    27
//
sl@0
    28
// we need these later in the example
sl@0
    29
//
sl@0
    30
#include <boost/assert.hpp>
sl@0
    31
#include <string>
sl@0
    32
#include <exception>
sl@0
    33
sl@0
    34
sl@0
    35
//
sl@0
    36
// Then we define a small polymorphic class
sl@0
    37
// hierarchy.
sl@0
    38
// 
sl@0
    39
sl@0
    40
class animal : boost::noncopyable
sl@0
    41
{
sl@0
    42
    virtual std::string do_speak() const = 0;
sl@0
    43
    std::string name_;
sl@0
    44
sl@0
    45
protected:
sl@0
    46
    //
sl@0
    47
    // Animals cannot be copied...
sl@0
    48
    //
sl@0
    49
    animal( const animal& r ) : name_( r.name_ )           { }
sl@0
    50
    void operator=( const animal& );
sl@0
    51
sl@0
    52
private:
sl@0
    53
    //
sl@0
    54
    // ...but due to advances in genetics, we can clone them!
sl@0
    55
    //
sl@0
    56
sl@0
    57
    virtual animal* do_clone() const = 0;
sl@0
    58
        
sl@0
    59
public:
sl@0
    60
    animal( const std::string& name ) : name_(name)        { }
sl@0
    61
    virtual ~animal() throw()                              { }
sl@0
    62
    
sl@0
    63
    std::string speak() const
sl@0
    64
    {
sl@0
    65
        return do_speak();
sl@0
    66
    }
sl@0
    67
sl@0
    68
    std::string name() const
sl@0
    69
    {
sl@0
    70
        return name_;
sl@0
    71
    }
sl@0
    72
sl@0
    73
    animal* clone() const
sl@0
    74
    {
sl@0
    75
        return do_clone();
sl@0
    76
    }
sl@0
    77
};
sl@0
    78
sl@0
    79
//
sl@0
    80
// An animal is still not Clonable. We need this last hook.
sl@0
    81
//
sl@0
    82
// Notice that we pass the animal by const reference
sl@0
    83
// and return by pointer.
sl@0
    84
//
sl@0
    85
sl@0
    86
animal* new_clone( const animal& a )
sl@0
    87
{
sl@0
    88
    return a.clone();
sl@0
    89
}
sl@0
    90
sl@0
    91
//
sl@0
    92
// We do not need to define 'delete_clone()' since
sl@0
    93
// since the default is to call the default 'operator delete()'.
sl@0
    94
//
sl@0
    95
sl@0
    96
const std::string muuuh = "Muuuh!";
sl@0
    97
const std::string oiink = "Oiiink";
sl@0
    98
sl@0
    99
class cow : public animal
sl@0
   100
{
sl@0
   101
    virtual std::string do_speak() const
sl@0
   102
    {
sl@0
   103
        return muuuh;
sl@0
   104
    }
sl@0
   105
sl@0
   106
    virtual animal* do_clone() const
sl@0
   107
    {
sl@0
   108
        return new cow( *this );
sl@0
   109
    }
sl@0
   110
sl@0
   111
public:
sl@0
   112
    cow( const std::string& name ) : animal(name)          { }
sl@0
   113
};
sl@0
   114
sl@0
   115
class pig : public animal
sl@0
   116
{
sl@0
   117
    virtual std::string do_speak() const
sl@0
   118
    {
sl@0
   119
        return oiink;
sl@0
   120
    }
sl@0
   121
sl@0
   122
    virtual animal* do_clone() const
sl@0
   123
    {
sl@0
   124
        return new pig( *this );
sl@0
   125
    }
sl@0
   126
    
sl@0
   127
public:
sl@0
   128
    pig( const std::string& name ) : animal(name)          { }
sl@0
   129
};
sl@0
   130
sl@0
   131
//
sl@0
   132
// Then we, of course, need a place to put all
sl@0
   133
// those animals.
sl@0
   134
//
sl@0
   135
sl@0
   136
class farm
sl@0
   137
{
sl@0
   138
    //
sl@0
   139
    // This is where the smart containers are handy
sl@0
   140
    //
sl@0
   141
    typedef boost::ptr_deque<animal> barn_type;
sl@0
   142
    barn_type                        barn;
sl@0
   143
sl@0
   144
    //
sl@0
   145
    // An error type
sl@0
   146
    //
sl@0
   147
    struct farm_trouble : public std::exception           { };
sl@0
   148
sl@0
   149
public:
sl@0
   150
    // 
sl@0
   151
    // We would like to make it possible to
sl@0
   152
    // iterate over the animals in the farm
sl@0
   153
    //
sl@0
   154
    typedef barn_type::iterator  animal_iterator;
sl@0
   155
sl@0
   156
    //
sl@0
   157
    // We also need to count the farm's size...
sl@0
   158
    //
sl@0
   159
    typedef barn_type::size_type size_type;
sl@0
   160
    
sl@0
   161
    //
sl@0
   162
    // And we also want to transfer an animal
sl@0
   163
    // safely around. The easiest way to think
sl@0
   164
    // about '::auto_type' is to imagine a simplified
sl@0
   165
    // 'std::auto_ptr<T>' ... this means you can expect
sl@0
   166
    // 
sl@0
   167
    //   T* operator->()
sl@0
   168
    //   T* release()
sl@0
   169
    //   deleting destructor
sl@0
   170
    //
sl@0
   171
    // but not more.
sl@0
   172
    //
sl@0
   173
    typedef barn_type::auto_type  animal_transport;
sl@0
   174
sl@0
   175
    // 
sl@0
   176
    // Create an empty farm.
sl@0
   177
    //
sl@0
   178
    farm()                                                 { }
sl@0
   179
    
sl@0
   180
    //
sl@0
   181
    // We need a constructor that can make a new
sl@0
   182
    // farm by cloning a range of animals.
sl@0
   183
    //
sl@0
   184
    farm( animal_iterator begin, animal_iterator end )
sl@0
   185
     : 
sl@0
   186
        //
sl@0
   187
        // Objects are always cloned before insertion
sl@0
   188
        // unless we explicitly add a pointer or 
sl@0
   189
        // use 'release()'. Therefore we actually
sl@0
   190
        // clone all animals in the range
sl@0
   191
        //
sl@0
   192
        barn( begin, end )                               { }
sl@0
   193
    
sl@0
   194
    //
sl@0
   195
    // ... so we need some other function too
sl@0
   196
    //
sl@0
   197
sl@0
   198
    animal_iterator begin()
sl@0
   199
    {
sl@0
   200
        return barn.begin();
sl@0
   201
    }
sl@0
   202
sl@0
   203
    animal_iterator end()
sl@0
   204
    {
sl@0
   205
        return barn.end();
sl@0
   206
    }
sl@0
   207
    
sl@0
   208
    //
sl@0
   209
    // Here it is quite ok to have an 'animal*' argument.
sl@0
   210
    // The smart container will handle all ownership
sl@0
   211
    // issues.
sl@0
   212
    //
sl@0
   213
    void buy_animal( animal* a )
sl@0
   214
    {
sl@0
   215
        barn.push_back( a );
sl@0
   216
    }
sl@0
   217
sl@0
   218
    //
sl@0
   219
    // The farm can also be in economical trouble and
sl@0
   220
    // therefore be in the need to sell animals.
sl@0
   221
    //
sl@0
   222
    animal_transport sell_animal( animal_iterator to_sell )
sl@0
   223
    {
sl@0
   224
        if( to_sell == end() )
sl@0
   225
            throw farm_trouble();
sl@0
   226
sl@0
   227
        //
sl@0
   228
        // Here we remove the animal from the barn,
sl@0
   229
        // but the animal is not deleted yet...it's
sl@0
   230
        // up to the buyer to decide what
sl@0
   231
        // to do with it.
sl@0
   232
        //
sl@0
   233
        return barn.release( to_sell );
sl@0
   234
    }
sl@0
   235
sl@0
   236
    //
sl@0
   237
    // How big a farm do we have?
sl@0
   238
    //
sl@0
   239
    size_type size() const
sl@0
   240
    {
sl@0
   241
        return barn.size();
sl@0
   242
    }
sl@0
   243
sl@0
   244
    //
sl@0
   245
    // If things are bad, we might choose to sell all animals :-(
sl@0
   246
    //
sl@0
   247
    std::auto_ptr<barn_type> sell_farm()
sl@0
   248
    {
sl@0
   249
        return barn.release();
sl@0
   250
    }
sl@0
   251
sl@0
   252
    //
sl@0
   253
    // However, if things are good, we might buy somebody
sl@0
   254
    // else's farm :-)
sl@0
   255
    //
sl@0
   256
sl@0
   257
    void buy_farm( std::auto_ptr<barn_type> other )
sl@0
   258
    {
sl@0
   259
        //
sl@0
   260
        // This line inserts all the animals from 'other'
sl@0
   261
        // and is guaranteed either to succeed or to have no
sl@0
   262
        // effect
sl@0
   263
        //
sl@0
   264
        barn.transfer( barn.end(), // insert new animals at the end
sl@0
   265
                         *other );     // we want to transfer all animals,
sl@0
   266
                                       // so we use the whole container as argument
sl@0
   267
        //
sl@0
   268
        // You might think you would have to do
sl@0
   269
        //
sl@0
   270
        // other.release();
sl@0
   271
        //
sl@0
   272
        // but '*other' is empty and can go out of scope as it wants
sl@0
   273
        //
sl@0
   274
        BOOST_ASSERT( other->empty() );
sl@0
   275
    }
sl@0
   276
    
sl@0
   277
}; // class 'farm'.
sl@0
   278
sl@0
   279
#include <boost/test/included/test_exec_monitor.hpp>
sl@0
   280
int test_main(int,char *[])
sl@0
   281
{
sl@0
   282
    //
sl@0
   283
    // First we make a farm
sl@0
   284
    //
sl@0
   285
    farm animal_farm;
sl@0
   286
    BOOST_ASSERT( animal_farm.size() == 0u );
sl@0
   287
    
sl@0
   288
    animal_farm.buy_animal( new pig("Betty") );
sl@0
   289
    animal_farm.buy_animal( new pig("Benny") );
sl@0
   290
    animal_farm.buy_animal( new pig("Jeltzin") );
sl@0
   291
    animal_farm.buy_animal( new cow("Hanz") );
sl@0
   292
    animal_farm.buy_animal( new cow("Mary") );
sl@0
   293
    animal_farm.buy_animal( new cow("Frederik") );
sl@0
   294
    BOOST_ASSERT( animal_farm.size() == 6u );
sl@0
   295
sl@0
   296
    //
sl@0
   297
    // Then we make another farm...it will actually contain
sl@0
   298
    // a clone of the other farm.
sl@0
   299
    //
sl@0
   300
    farm new_farm( animal_farm.begin(), animal_farm.end() );
sl@0
   301
    BOOST_ASSERT( new_farm.size() == 6u );
sl@0
   302
sl@0
   303
    //
sl@0
   304
    // Is it really clones in the new farm?
sl@0
   305
    //
sl@0
   306
    BOOST_ASSERT( new_farm.begin()->name() == "Betty" );
sl@0
   307
    
sl@0
   308
    //
sl@0
   309
    // Then we search for an animal, Mary (the Crown Princess of Denmark),
sl@0
   310
    // because we would like to buy her ...
sl@0
   311
    //
sl@0
   312
    typedef farm::animal_iterator iterator;
sl@0
   313
    iterator to_sell;
sl@0
   314
    for( iterator i   = animal_farm.begin(),
sl@0
   315
                  end = animal_farm.end();
sl@0
   316
         i != end; ++i )
sl@0
   317
    {
sl@0
   318
        if( i->name() == "Mary" )
sl@0
   319
        {
sl@0
   320
            to_sell = i;
sl@0
   321
            break;
sl@0
   322
        }
sl@0
   323
    }
sl@0
   324
sl@0
   325
    farm::animal_transport mary = animal_farm.sell_animal( to_sell );
sl@0
   326
sl@0
   327
sl@0
   328
    if( mary->speak() == muuuh )
sl@0
   329
        //
sl@0
   330
        // Great, Mary is a cow, and she may live longer
sl@0
   331
        //
sl@0
   332
        new_farm.buy_animal( mary.release() );
sl@0
   333
    else
sl@0
   334
        //
sl@0
   335
        // Then the animal would be destroyed (!)
sl@0
   336
        // when we go out of scope.
sl@0
   337
        //
sl@0
   338
        ;
sl@0
   339
sl@0
   340
    //
sl@0
   341
    // Now we can observe some changes to the two farms...
sl@0
   342
    //
sl@0
   343
    BOOST_ASSERT( animal_farm.size() == 5u );
sl@0
   344
    BOOST_ASSERT( new_farm.size()    == 7u );
sl@0
   345
sl@0
   346
    //
sl@0
   347
    // The new farm has however underestimated how much
sl@0
   348
    // it cost to feed Mary and its owner is forced to sell the farm...
sl@0
   349
    //
sl@0
   350
    animal_farm.buy_farm( new_farm.sell_farm() );
sl@0
   351
sl@0
   352
    BOOST_ASSERT( new_farm.size()    == 0u );
sl@0
   353
    BOOST_ASSERT( animal_farm.size() == 12u );     
sl@0
   354
	return 0;
sl@0
   355
}