$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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;
+}