270 likes | 319 Views
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
E N D
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
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 = list_of(1)(2)(3).to_container( v ); std::set<int> s = list_of(1)(2)(3)(4).to_container( s ); std::map<int,int> m = map_list_of(1,2)(2,3).to_container( m ); std::stack<int> st = list_of(1)(2)(3)(4).to_adapter( st ); std::queue<int> q = list_of(1)(2)(3)(4).to_adapter( q ); boost::array<int,4> a = list_of(1)(2)(3)(4).to_array( a );