Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r61857 - in sandbox/association: . boost boost/association libs libs/association libs/association/test
From: vicente.botet_at_[hidden]
Date: 2010-05-08 16:06:42


Author: viboes
Date: 2010-05-08 16:06:41 EDT (Sat, 08 May 2010)
New Revision: 61857
URL: http://svn.boost.org/trac/boost/changeset/61857

Log:
Added Association-bidir
Added:
   sandbox/association/
   sandbox/association/boost/
   sandbox/association/boost/association/
   sandbox/association/boost/association/association.hpp (contents, props changed)
   sandbox/association/libs/
   sandbox/association/libs/association/
   sandbox/association/libs/association/test/
   sandbox/association/libs/association/test/Jamfile.v2 (contents, props changed)
   sandbox/association/libs/association/test/basic_usage.cpp (contents, props changed)

Added: sandbox/association/boost/association/association.hpp
==============================================================================
--- (empty file)
+++ sandbox/association/boost/association/association.hpp 2010-05-08 16:06:41 EDT (Sat, 08 May 2010)
@@ -0,0 +1,292 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2010.
+// Distributed under the Boost
+// Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/association for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_BIASSOCIATION__HPP
+#define BOOST_BIASSOCIATION__HPP
+
+#include <stddef.h>
+#include <boost/assert.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost {
+ template <typename Type,typename Tag>
+struct tagged {
+ typedef Type type;
+ typedef Tag tag;
+};
+
+namespace member_at {
+ struct left{};
+ struct right{};
+}
+
+template <typename T>
+struct tagged_traits {
+ typedef T type;
+ typedef member_at::left tag;
+};
+
+template <typename T, typename Tag>
+struct tagged_traits<tagged<T,Tag> > {
+ typedef T type;
+ typedef Tag tag;
+};
+
+
+// specializations of get_field must define a static function apply
+// with the following prototype
+// typename TaggedType::type& apply(T&);
+
+template <typename TaggedType, typename T>
+struct get_field;
+
+// specializations of get_embeding must define a static function apply
+// with the following prototype
+// T& apply(FieldType&);
+
+template <typename T, typename Tag, typename FieldType>
+struct get_embeding;
+
+
+
+namespace association {
+
+
+template <typename T, typename U>
+class end_ptr {
+
+public:
+ typedef typename tagged_traits<T>::type own_type;
+ typedef typename tagged_traits<T>::tag own_tag;
+ typedef typename tagged_traits<U>::type other_type;
+ typedef typename tagged_traits<U>::tag other_tag;
+private:
+ other_type* other_ptr_;
+
+public:
+
+ typedef other_type element_type;
+ typedef other_type value_type;
+ typedef other_type * pointer;
+
+ end_ptr() : other_ptr_(0) {}
+
+ ~end_ptr()
+ {
+ disconnect();
+ }
+
+ element_type* get()
+ {
+ return other_ptr_;
+ }
+
+ const other_type* operator-> () const
+ {
+ BOOST_ASSERT(get() != 0);
+ return get();
+ }
+ other_type* operator-> ()
+ {
+ BOOST_ASSERT(get() != 0);
+ return get();
+ }
+
+ other_type const& operator* () const
+ {
+ BOOST_ASSERT(get() != 0);
+ return *get();
+ }
+
+ other_type& operator* ()
+ {
+ BOOST_ASSERT(get() != 0);
+ return *get();
+ }
+
+ // C c; c.f=&u;
+ end_ptr& operator=(other_type* ptr) {
+ connect(ptr);
+ return *this;
+ }
+ end_ptr& operator=(end_ptr& rhs) {
+ if (this!= &rhs) {
+ disconnect();
+ connect(rhs.other_ptr_);
+ }
+ return *this;
+ }
+
+ void swap(end_ptr& other)
+ {
+ U* own_u = other_ptr_;
+ U* other_u = other.other_ptr_;
+
+ connect(other_u);
+ other.connect(own_u);
+ }
+
+ void connect(other_type* ptr)
+ {
+ if(ptr == other_ptr_) return;
+ disconnect();
+ if(ptr == 0) return;
+ other_ptr_ = ptr;
+ get_field<tagged<end_ptr<U,T>,own_tag>, other_type>::apply(*ptr).connect_one(
+ &get_embeding<own_type, own_tag, end_ptr<T,U> >::apply(*this));
+ }
+
+ void disconnect()
+ {
+ if(other_ptr_==0) return;
+ other_type* tmp = other_ptr_;
+ other_ptr_= 0;
+ get_field<tagged<end_ptr<U,T>,own_tag>, other_type>::apply(*tmp).disconnect_one();
+ }
+
+ friend class end_ptr<U, T>;
+
+protected:
+
+ void connect_one(other_type* ptr)
+ {
+ if(ptr == other_ptr_) return;
+ disconnect();
+ other_ptr_ = ptr;
+ }
+
+ void disconnect_one()
+ {
+ if(other_ptr_==0) return;
+ other_ptr_ = 0;
+ }
+};
+
+template <typename T, typename U>
+class bidir {
+public:
+ typedef typename tagged_traits<T>::type left_type;
+ typedef typename tagged_traits<T>::tag left_tag;
+ typedef typename tagged_traits<U>::type right_type;
+ typedef typename tagged_traits<U>::tag right_tag;
+ typedef end_ptr<T,U> left_end_point;
+ typedef end_ptr<U,T> right_end_point;
+
+public:
+ template <typename WTag>
+ struct end_point {
+ typedef typename mpl::if_<is_same<WTag,right_tag>, left_end_point,
+ typename mpl::if_<is_same<WTag,left_tag>, right_end_point,
+ void>::type
+ >::type
+ type;
+ };
+
+#if 0
+ template <typename WTag>
+ static typename enable_if<is_same<WTag,right_tag>, right_type*> ::type
+ //~ static void
+ get(left_type& ptr)
+ {
+ return get_field<tagged<left_end_point, right_tag>, left_type>::apply(ptr).get();
+ }
+
+ template <typename WTag>
+ static typename enable_if<is_same<WTag,left_tag>, left_type*> ::type
+ //~ static void
+ get(right_type& ptr)
+ {
+ return get_field<tagged<right_end_point, left_tag>, right_type>::apply(ptr).get();
+ }
+
+#endif
+ static left_end_point& get_left_end_point(left_type& lptr) {
+ return get_field<tagged<left_end_point, right_tag>, left_type>::apply(lptr);
+ }
+ static right_end_point& get_right_end_point(right_type& lptr) {
+ return get_field<tagged<right_end_point, left_tag>, right_type>::apply(lptr);
+ }
+
+ template <typename WTag>
+ static typename enable_if<is_same<WTag,right_tag>, right_type*>::type
+ //~ static void
+ get(left_type& ptr)
+ {
+ return get_field<tagged<left_end_point, right_tag>, left_type>::apply(ptr).get();
+ }
+
+ template <typename WTag>
+ static typename enable_if<is_same<WTag,left_tag>, left_type*> ::type
+ //~ static void
+ get(right_type& ptr)
+ {
+ return get_field<tagged<right_end_point, left_tag>, right_type>::apply(ptr).get();
+ }
+
+ static void connect(left_type* lptr, right_type* rptr)
+ {
+ if (lptr!=0) {
+ get_left_end_point(*lptr).connect(rptr);
+ } else if(rptr!=0) {
+ get_right_end_point(*rptr).connect(lptr);
+ }
+ }
+
+ template <typename WTag>
+ static typename enable_if<is_same<WTag,left_tag>, void>::type
+ //~ static void
+ disconnect(left_type& ptr)
+ {
+ get_left_end_point(ptr).disconnect();
+ }
+
+ template <typename WTag>
+ static typename enable_if<is_same<WTag,right_tag>, void> ::type
+ //~ static void
+ disconnect(right_type& ptr)
+ {
+ get_right_end_point(ptr).disconnect();
+ }
+
+};
+
+} // namespace association
+} // namespace boost
+
+#define BOOST_GET_OBJECT(T, FIELD, VAR) \
+ *(reinterpret_cast<T*>(reinterpret_cast<char*>(&VAR) - offsetof(T, FIELD)))
+
+#define BOOST_ASSOCIATION_FIELD_DCL(A,ATAG, B, BTAG, FIELD)\
+namespace boost {\
+template <>\
+struct get_field<tagged<association::end_ptr<tagged<A,ATAG>,tagged<B,BTAG> >,BTAG>,A> {\
+ static association::end_ptr<tagged<A,ATAG>,tagged<B,BTAG> >& apply(A&v) {\
+ return v.FIELD;\
+ }\
+};\
+ \
+template <>\
+struct get_embeding<A,ATAG,association::end_ptr<tagged<A,ATAG>,tagged<B,BTAG> > > {\
+ static A& apply(association::end_ptr<tagged<A,ATAG>,tagged<B,BTAG> >&v) {\
+ return BOOST_GET_OBJECT(A, FIELD, v);\
+ }\
+};\
+}
+
+#define BOOST_ASSOCIATION_DCL(ASSOC, LEFT, RIGHT) \
+BOOST_ASSOCIATION_FIELD_DCL(ASSOC::left_type, ASSOC::left_tag, ASSOC::right_type, ASSOC::right_tag, RIGHT); \
+BOOST_ASSOCIATION_FIELD_DCL(ASSOC::right_type, ASSOC::right_tag, ASSOC::left_type, ASSOC::left_tag, LEFT)
+
+
+#endif

Added: sandbox/association/libs/association/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/association/libs/association/test/Jamfile.v2 2010-05-08 16:06:41 EDT (Sat, 08 May 2010)
@@ -0,0 +1,39 @@
+# Boost Association Library test Jamfile
+
+# Copyright Vicente Botet 2010
+
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt
+
+# See library home page at http://www.boost.org/libs/association
+
+# uncomment one if the above lines if you build outside the Boost release
+#local BOOST_ROOT = /boost_1_41_0 ;
+#local BOOST_ROOT = c:/cygwin/boost_1_41_0 ;
+
+if ! $(BOOST_ROOT)
+{
+ BOOST_ROOT = [ modules.peek : BOOST_ROOT ] ;
+}
+
+project
+ : requirements
+ <library>/boost/test//boost_unit_test_framework/<link>static
+
+ # uncomment the line above if you build outside the Boost release
+ #<include>$(BOOST_ROOT)
+ # uncomment the line above if you build outside the Boost release
+ #<include>../../..
+# <toolset>msvc:<asynch-exceptions>on
+ ;
+
+ test-suite "association"
+ :
+ [ run basic_usage.cpp ]
+ ;
+
+# test-suite "compile_fail"
+# :
+# [ compile-fail xxx.cpp ]
+# ;
+

Added: sandbox/association/libs/association/test/basic_usage.cpp
==============================================================================
--- (empty file)
+++ sandbox/association/libs/association/test/basic_usage.cpp 2010-05-08 16:06:41 EDT (Sat, 08 May 2010)
@@ -0,0 +1,91 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2010.
+// Distributed under the Boost
+// Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/association for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/association/association.hpp>
+#include <iostream>
+
+using namespace boost;
+
+class CBoy;
+class CGirl;
+
+struct boy {};
+struct girl {};
+
+typedef association::bidir<
+ tagged<CBoy, boy>,
+ tagged<CGirl, girl>
+> friends;
+
+class CBoy {
+public:
+ CBoy() {}
+ void GiveGirlfriendFlowers();
+ void RecvSlap() {
+ std::cout << "boy: ouch!" << '\n';
+ m_girlfriend.disconnect();
+ }
+ //~ friends::left_end_point m_girlfriend;
+ friends::end_point<girl>::type m_girlfriend;
+};
+
+class CGirl {
+public:
+ CGirl() {
+ }
+ void RecvFlowers() {
+ std::cout << "girl: thank you for the flowers!" << '\n';
+ }
+ void SlapBoyfriend() {
+ std::cout << "girl: take this!" << '\n';
+ if(m_boyfriend.get())
+ m_boyfriend->RecvSlap();
+ }
+ void make_boyfriend() {
+ std::cout << "girl: i have a boyfriend!" << '\n';
+ }
+ void break_boyfriend() {
+ std::cout << "girl: we broke up." << '\n';
+ }
+ //~ friends::right_end_point m_boyfriend;
+ friends::end_point<boy>::type m_boyfriend;
+};
+
+void CBoy::GiveGirlfriendFlowers() {
+ //~ if(m_girlfriend.get())
+ //~ m_girlfriend->RecvFlowers();
+
+ if (friends::get<girl>(*this))
+ friends::get<girl>(*this)->RecvFlowers();
+
+}
+
+BOOST_ASSOCIATION_DCL(friends, m_boyfriend, m_girlfriend);
+
+
+int main()
+{
+ CBoy Henry;
+ CGirl Sally;
+
+ //~ Henry.m_girlfriend.connect(&Sally);
+ friends::connect(&Henry,&Sally);
+ friends::disconnect<boy>(Henry);
+ friends::connect(&Henry,&Sally);
+ friends::disconnect<girl>(Sally);
+ friends::connect(&Henry,&Sally);
+ Henry.GiveGirlfriendFlowers();
+ //~ Sally.SlapBoyfriend();
+ friends::get<girl>(Henry)->SlapBoyfriend();
+
+ return 0;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk