Boost Candy A quick introduction to some libraries Boost? • • • • • Collection of C++ libraries and a community Meant to establish best practice Reference implementations for future C++ standards Widely used, well tested, industrial strength code Portable Smart pointers library • • • • scoped_ptr shared_ptr weak_ptr intrusive_ptr scoped_ptr { boost::scoped_ptr<int> ptr(new int); ... } class X { private: boost::scoped_ptr<SomeClass> iPtr; }; boost::scoped_ptr<int> get_ptr (); // Illegal shared_ptr boost::shared_ptr<int> get_ptr () { boost::shared_ptr<int> local_ptr(new int); return local_ptr; } { boost::shared_ptr<int> ptr; ptr = get_ptr(); } shared_ptr caveats struct C { boost::shared_ptr<C> mNeighbour; }; { boost::shared_ptr<C> a(new C), b(new C); a->mNeighbour = b; b->mNeighbour = a; } shared_ptr caveats Consider: call(boost::shared_ptr<Foo>(new Foo(...)), throwing_call()) shared_ptr caveats Always use named variables: boost::shared_ptr<Foo> foo(new Foo(...)); call(foo, throwing_call()) weak_ptr namespace { weak_ptr<SomeClass> cache; } shared_ptr<SomeClass> cached_get() { shared_ptr<SomeClass> ptr = cache.lock(); if (!ptr) { ptr.reset(new SomeClass(...)); cache = ptr; } return ptr; } intrusive_ptr Interface with libraries that uses internal reference counts Smart pointers Don’t use shared_array and scoped_array Use shared/scoped pointer to std::vector, boost::array Full STL compliance Smart pointers comparison boost::shared_ptr shared ownership boost::weak_ptr break circular ownership, implement cache boost::scoped_ptr RAII boost::intrusive_ptr Interface 3rd party libraries std::auto_ptr Sole, transferable ownership boost::optional Some functions only sometimes return a value double sqrt(double n) char get_async_input() point polygon::get_any_point_effectively_inside( ) boost::optional Alternatives to cope with this: • • • • Required pre-condition and undefined behaviour Throw exception Special value (i.e. zero, inf) Return std::pair<bool, return_value> boost::optional approach Single-element container, contain 0 or 1 element boost::optional example boost::optional<double> sqrt(double n) { boost::optional<double> result; if (n >= 0) result = sqrt_helper(n); return result; } boost::optional<double> root = sqrt(n); if (root) std::cout << *root; boost::optional example enum ChessPiece { WHITE_KING, BLACK_KING, …}; typedef std::vector< std::vector< boost::optional<ChessPiece> > > ChessBoard; ChessBoard board(…); board.at(0).at(3) = WHITE_KING; board.at(7).at(4) = BLACK_KING; boost::optional approach • Deep copy semantics copies of the container implies copies of the value • Deep relational semantics compare container size and if match, contained value boost::optional benefits • Easy to read • Intuitive value semantics – principle of least astonishment • ==, !=, <, >, <=, >= boost::assign purpose Easy to fill containers Both insert and initialize boost::assign example #include <boost/assign/std/vector.hpp> // For += using namespace boost::assign; { std::vector<int> values = (-2) (-1) (0); values += 1,2,3,4,5,6,7,8,9; } boost::assign example #include <boost/assign/map_list_of.hpp> #include <boost/assign/list_inserter.hpp> namespace boost::assign = ba; { std::map<int, std::string> mapping = ba::map_list_of (1, ”one”) (2, ”two”); ba::insert(mapping) (3, ”three”) (4, ”four”); } boost::assign example #include <boost/assign/list_inserter.hpp> { std::list<int> list; boost::assign::push_front(list) (1) (2) (3); } boost::assign example #include <boost/assign.hpp> using namespace boost::assign; { // 1,2,2,2,2,2,3 std::vector<int> = 1, repeat(5, 2), 3; } boost::assign example std::map<std::string, std::list<int> > numbers = map_list_of ( ”Primes", list_of (1)(2)(3)(5) ) ( ”Zero", list_of (0) ) ( ”Odd", list_of (1)(3)(5)(7) ); boost::assign problems • Compilers not supporting templates full out • Not 100% STL compliant std-lib implementations boost::assign work-arounds std::vector<int> v std::set<int> s ); std::map<int,int> m m ); std::stack<int> st ); std::queue<int> q ); = list_of(1)(2)(3).to_container( v ); = list_of(1)(2)(3)(4).to_container( s = map_list_of(1,2)(2,3).to_container( = list_of(1)(2)(3)(4).to_adapter( st = list_of(1)(2)(3)(4).to_adapter( q boost::array<int,4> a = list_of(1)(2)(3)(4).to_array( a );