#include <boost/ptr_container/ptr_deque.hpp>
#include <boost/assert.hpp>
#include <string>
#include <exception>
class animal : boost::noncopyable
{
virtual std::string do_speak() const = 0;
std::string name_;
protected:
animal( const animal& r ) : name_( r.name_ ) { }
void operator=( const animal& );
private:
virtual animal* do_clone() const = 0;
public:
animal( const std::string& name ) : name_(name) { }
virtual ~animal() throw() { }
std::string speak() const
{
return do_speak();
}
std::string name() const
{
return name_;
}
animal* clone() const
{
return do_clone();
}
};
animal* new_clone( const animal& a )
{
return a.clone();
}
const std::string muuuh = "Muuuh!";
const std::string oiink = "Oiiink";
class cow : public animal
{
virtual std::string do_speak() const
{
return muuuh;
}
virtual animal* do_clone() const
{
return new cow( *this );
}
public:
cow( const std::string& name ) : animal(name) { }
};
class pig : public animal
{
virtual std::string do_speak() const
{
return oiink;
}
virtual animal* do_clone() const
{
return new pig( *this );
}
public:
pig( const std::string& name ) : animal(name) { }
};
class farm
{
typedef boost::ptr_deque<animal> barn_type;
barn_type barn;
#if !defined(BOOST_NO_CXX11_SMART_PTR) && !(defined(BOOST_MSVC) && BOOST_MSVC == 1600) && !BOOST_WORKAROUND(BOOST_GCC, < 40600)
typedef std::unique_ptr<barn_type> raii_ptr;
#else
typedef std::auto_ptr<barn_type> raii_ptr;
#endif
struct farm_trouble : public std::exception { };
public:
typedef barn_type::iterator animal_iterator;
typedef barn_type::size_type size_type;
typedef barn_type::auto_type animal_transport;
farm() { }
farm( animal_iterator begin, animal_iterator end )
:
barn( begin, end ) { }
animal_iterator begin()
{
return barn.begin();
}
animal_iterator end()
{
return barn.end();
}
void buy_animal( animal* a )
{
barn.push_back( a );
}
animal_transport sell_animal( animal_iterator to_sell )
{
if( to_sell == end() )
throw farm_trouble();
return barn.release( to_sell );
}
size_type size() const
{
return barn.size();
}
raii_ptr sell_farm()
{
return barn.release();
}
void buy_farm( raii_ptr other )
{
barn.transfer( barn.end(), *other ); BOOST_ASSERT( other->empty() );
}
};
int main()
{
farm animal_farm;
BOOST_ASSERT( animal_farm.size() == 0u );
animal_farm.buy_animal( new pig("Betty") );
animal_farm.buy_animal( new pig("Benny") );
animal_farm.buy_animal( new pig("Jeltzin") );
animal_farm.buy_animal( new cow("Hanz") );
animal_farm.buy_animal( new cow("Mary") );
animal_farm.buy_animal( new cow("Frederik") );
BOOST_ASSERT( animal_farm.size() == 6u );
farm new_farm( animal_farm.begin(), animal_farm.end() );
BOOST_ASSERT( new_farm.size() == 6u );
BOOST_ASSERT( new_farm.begin()->name() == "Betty" );
typedef farm::animal_iterator iterator;
iterator to_sell;
for( iterator i = animal_farm.begin(),
end = animal_farm.end();
i != end; ++i )
{
if( i->name() == "Mary" )
{
to_sell = i;
break;
}
}
farm::animal_transport mary = animal_farm.sell_animal( to_sell );
if( mary->speak() == muuuh )
new_farm.buy_animal( mary.release() );
else
;
BOOST_ASSERT( animal_farm.size() == 5u );
BOOST_ASSERT( new_farm.size() == 7u );
animal_farm.buy_farm( new_farm.sell_farm() );
BOOST_ASSERT( new_farm.size() == 0u );
BOOST_ASSERT( animal_farm.size() == 12u );
}