// file : odb/view-result.hxx // copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file #ifndef ODB_VIEW_RESULT_HXX #define ODB_VIEW_RESULT_HXX #include #include // std::ptrdiff_t, std::size_t #include // iterator categories #include // std::move #include #include #include #include #include // ODB_CXX11 namespace odb { template class view_result_impl: public result_impl { protected: friend class result; friend class result; friend class result_iterator; friend class result_iterator; // In result_impl, T is always non-const and the same as view_type. // typedef T view_type; typedef odb::view_traits view_traits; typedef typename view_traits::pointer_type pointer_type; typedef odb::pointer_traits pointer_traits; view_result_impl (connection& conn) : result_impl (conn), begin_ (true), end_ (false), current_ () { } // To make this work with all kinds of pointers (raw, std::auto_ptr, // shared), we need to make sure we don't make any copies of the // pointer on the return path. // pointer_type& current (); void release () { current_ = pointer_type (); guard_.release (); } void begin () { if (begin_) { next (); begin_ = false; } } bool end () const { return end_; } protected: virtual void load (view_type&) = 0; virtual void next () = 0; virtual void cache () = 0; virtual std::size_t size () = 0; protected: #ifdef ODB_CXX11 void current (pointer_type& p) { current_ = std::move (p); guard_.reset (current_); } void current (pointer_type&& p) { current (p); } #else void current (pointer_type p) { current_ = p; guard_.reset (current_); } #endif bool begin_; bool end_; private: pointer_type current_; typename pointer_traits::guard guard_; }; template class result_iterator { public: typedef T value_type; typedef value_type& reference; typedef value_type* pointer; typedef std::ptrdiff_t difference_type; typedef std::input_iterator_tag iterator_category; // T can be const T while view_type is always non-const. // typedef typename view_traits::view_type view_type; typedef view_result_impl result_impl_type; public: explicit result_iterator (result_impl_type* res = 0) : res_ (res) { } // Input iterator requirements. // public: reference operator* () const { return pointer_traits::get_ref (res_->current ()); } // Our value_type is already a pointer so return it instead of // a pointer to it (operator-> will just have to go one deeper // in the latter case). // pointer operator-> () const { return pointer_traits::get_ptr (res_->current ()); } result_iterator& operator++ () { res_->next (); return *this; } result_iterator operator++ (int) { // All non-end iterators for a result object move together. // res_->next (); return *this; } public: typename view_traits::pointer_type load () { typename view_traits::pointer_type r (res_->current ()); res_->release (); return r; } void load (view_type&); public: bool equal (result_iterator j) const { return (res_ ? res_->end () : true) == (j.res_ ? j.res_->end () : true); } private: // Use unrestricted pointer traits since that's what is returned by // result_impl. // typedef odb::pointer_traits::pointer_type> pointer_traits; result_impl_type* res_; }; // // template class result_base { public: typedef typename view_traits::pointer_type value_type; // T can be const T while view_type is always non-const. // typedef typename view_traits::view_type view_type; typedef view_result_impl result_impl_type; }; } #include #include #endif // ODB_VIEW_RESULT_HXX