From ff208205f8ff9ec427d7464562a5e86007acb998 Mon Sep 17 00:00:00 2001 From: Andrea Rigoni Date: Wed, 3 Dec 2014 18:38:57 +0000 Subject: [PATCH] [uLib Geometry] + adds ClassCompound pattern --- src/Core/CMakeLists.txt | 1 + src/Core/ClassCompound.h | 175 ++++++++++++++++++++ src/Core/ClassFactory.h | 49 +++--- src/Core/Mpl.h | 3 + src/Core/testing/CMakeLists.txt | 1 + src/Core/testing/ClassCompoundTest.cpp | 215 +++++++++++++++++++++++++ src/Core/testing/ClassFactoryTest.cpp | 199 ++++++++--------------- 7 files changed, 488 insertions(+), 155 deletions(-) create mode 100644 src/Core/ClassCompound.h create mode 100644 src/Core/testing/ClassCompoundTest.cpp diff --git a/src/Core/CMakeLists.txt b/src/Core/CMakeLists.txt index fcc9757..e051f6c 100644 --- a/src/Core/CMakeLists.txt +++ b/src/Core/CMakeLists.txt @@ -24,6 +24,7 @@ set(HEADERS ProgrammableAccessor.h Named.h MplSequenceCombiner.h + ClassCompound.h ) SET(SOURCES diff --git a/src/Core/ClassCompound.h b/src/Core/ClassCompound.h new file mode 100644 index 0000000..e03e039 --- /dev/null +++ b/src/Core/ClassCompound.h @@ -0,0 +1,175 @@ +#ifndef U_CORE_CLASSCOMPOUND_H +#define U_CORE_CLASSCOMPOUND_H + + +#include "boost/type_traits.hpp" + +#include "Core/Mpl.h" + + +namespace uLib { +namespace detail { + + +template < class _Seq > +struct ClassCompound : ULIB_MPL_INHERIT_SEQ(_Seq) { + typedef _Seq Seq; + + ClassCompound() {} + + template < class S > + struct CopyOp { + CopyOp(const S * src, ClassCompound * const dst) : m_src(src), m_dst(dst) {} + + template < class T, bool b > + void copy(const T &t, const boost::integral_constant&) const { + } + + template < class T > + void copy(const T &t, const boost::true_type&) const { + static_cast(*m_dst) = t; + } + + template < class A > + void operator()(A) const { + const A &t = *m_src; + copy(t, boost::is_base_of()); + } + + ClassCompound * const m_dst; + const S *m_src; + }; + + template < class Other > + ClassCompound(const Other &t) { + typedef typename Other::Seq _seq; + mpl::for_each<_seq>(CopyOp(&t,this)); + } + + template < class Other > + const ClassCompound & operator = (const Other &t) { + typedef typename Other::Seq _seq; + mpl::for_each<_seq>(CopyOp(&t,this)); + return *this; + } + +}; + + +} // detail + + + +struct Null {}; +template < class T0 = Null, + class T1 = Null, + class T2 = Null, + class T3 = Null, + class T4 = Null, + class T5 = Null > +struct ClassCompound { + typedef T0 A0; + typedef T1 A1; + typedef T2 A2; + typedef T3 A3; + typedef T4 A4; + typedef T5 A5; + + //NEVER REACHED // +}; + +template < class _A0 > +struct ClassCompound<_A0> : detail::ClassCompound< mpl::vector<_A0> > { + + typedef detail::ClassCompound< mpl::vector<_A0> > BaseClass; + typedef _A0 A1; + + ClassCompound() {} + + template < class Other > + ClassCompound(const Other &t) : BaseClass(t) {} + + using BaseClass::operator =; +}; + +template < class _A0, + class _A1 > +struct ClassCompound<_A0,_A1> : detail::ClassCompound< mpl::vector<_A0,_A1> > { + typedef detail::ClassCompound< mpl::vector<_A0,_A1> > BaseClass; + typedef _A0 A0; + typedef _A1 A1; + + ClassCompound() {} + + template < class Other > + ClassCompound(const Other &t) : BaseClass(t) {} + + using BaseClass::operator =; +}; + +template < class _A0, + class _A1, + class _A2 > +struct ClassCompound<_A0,_A1,_A2> : detail::ClassCompound< mpl::vector<_A0,_A1,_A2> > { + + typedef detail::ClassCompound< mpl::vector<_A0,_A1,_A2> > BaseClass; + typedef _A0 A0; + typedef _A1 A1; + typedef _A2 A2; + + + ClassCompound() {} + + template < class Other > + ClassCompound(const Other &t) : BaseClass(t) {} + + using BaseClass::operator =; +}; + +template < class _A0, + class _A1, + class _A2, + class _A3 > +struct ClassCompound<_A0,_A1,_A2,_A3> : detail::ClassCompound< mpl::vector<_A0,_A1,_A2,_A3> > { + + typedef detail::ClassCompound< mpl::vector<_A0,_A1,_A2,_A3> > BaseClass; + typedef _A0 A0; + typedef _A1 A1; + typedef _A2 A2; + typedef _A3 A3; + + ClassCompound() {} + + template < class Other > + ClassCompound(const Other &t) : BaseClass(t) {} + + using BaseClass::operator =; +}; + +template < class _A0, + class _A1, + class _A2, + class _A3, + class _A4 > +struct ClassCompound<_A0,_A1,_A2,_A3,_A4> : detail::ClassCompound< mpl::vector<_A0,_A1,_A2,_A3,_A4> > { + + typedef detail::ClassCompound< mpl::vector<_A0,_A1,_A2,_A3,_A4> > BaseClass; + typedef _A0 A0; + typedef _A1 A1; + typedef _A2 A2; + typedef _A3 A3; + typedef _A4 A4; + + ClassCompound() {} + + template < class Other > + ClassCompound(const Other &t) : BaseClass(t) {} + + using BaseClass::operator =; +}; + +} // uLib + + + +#endif // CLASSCOMPOUND_H diff --git a/src/Core/ClassFactory.h b/src/Core/ClassFactory.h index df71c82..719d58f 100644 --- a/src/Core/ClassFactory.h +++ b/src/Core/ClassFactory.h @@ -19,12 +19,11 @@ namespace uLib { //////////////////////////////////////////////////////////////////////////////// // generator // -template -static BaseType * newClass() { return new T; } - - - +template +static void * newClass() { return new T; } +template +static void * newClass2(void *a1,void *a2) { return new T(a1,a2); } @@ -34,18 +33,18 @@ static BaseType * newClass() { return new T; } template class NamedClassFactory { - typedef BaseType*(*_newClassfn)(); + typedef void * (*_newClassfn)(); typedef std::map MapType; public: template void AddType(const char* name) { - m_map.insert(std::make_pair(name, &newClass)); + m_map.insert(std::make_pair(name, &newClass)); } BaseType *Create(const char *type) { typename MapType::iterator itr = m_map.find(type); - return itr->second(); + return static_cast(itr->second()); } void List(std::ostream &o) { @@ -67,7 +66,7 @@ private: template class RegisteredClassFactory { - typedef BaseType*(*_newClassfn)(); + typedef void *(*_newClassfn)(); typedef std::vector<_newClassfn> TypeVectorType; struct AddTypeOp { @@ -79,7 +78,7 @@ class RegisteredClassFactory { }; template < typename T > - void addType() { m_map.push_back(&newClass); } + void addType() { m_map.push_back(&newClass); } public: @@ -97,7 +96,7 @@ public: BaseType *Create() { int id = Find(); typename TypeVectorType::iterator itr = m_map.begin() + id; - return (*itr)(); + return (BaseType *)(*itr)(); } private: @@ -116,12 +115,12 @@ template < typename S1 > class RegisteredClassFactory1 { - typedef BaseType*(*_newClassfn)(); + typedef void*(*_newClassfn)(); typedef std::vector<_newClassfn> TypeVectorType; template < typename U > void addType() { m_map.push_back(&newClass< - BaseType, +// BaseType, DerivedType >); } @@ -151,7 +150,7 @@ public: BaseType *Create(int id1) { typename TypeVectorType::iterator itr = m_map.begin() + id1; - return (*itr)(); + return (BaseType *)(*itr)(); } private: @@ -174,12 +173,12 @@ template < typename S2 > class RegisteredClassFactory2 { - typedef BaseType*(*_newClassfn)(); + typedef void*(*_newClassfn)(); typedef std::vector<_newClassfn> TypeVectorType; template < typename U, typename V > void addType() { m_map.push_back(&newClass< - BaseType, +// BaseType, DerivedType >); } @@ -196,12 +195,20 @@ class RegisteredClassFactory2 { }; typedef mpl::combine_view< mpl::vector > AlgView; + +// template < typename _T, class _Seq > +// static inline int find() { +// typedef typename mpl::find<_Seq,_T>::type iter; +// return iter::pos::value; +// } + public: RegisteredClassFactory2() { mpl::for_each< AlgView >(AddTypeSeqOp(this)); } + template < typename T > static inline int FindS1() { typedef typename mpl::find::type iter; @@ -215,9 +222,9 @@ public: } - BaseType *Create(int id1, int id2) { + BaseType * Create(int id1, int id2) { typename TypeVectorType::iterator itr = m_map.begin() + id1 + m_size1 * id2; - return (*itr)(); + return (BaseType *)(*itr)(); } private: @@ -243,12 +250,12 @@ template < typename S3 > class RegisteredClassFactory3 { - typedef BaseType*(*_newClassfn)(); + typedef void*(*_newClassfn)(); typedef std::vector<_newClassfn> TypeVectorType; template < typename T1, typename T2, typename T3 > void addType() { m_map.push_back(&newClass< - BaseType, +// BaseType, DerivedType >); } @@ -293,7 +300,7 @@ public: BaseType *Create(int id1, int id2, int id3) { typename TypeVectorType::iterator itr = m_map.begin() + id1 + m_size1 * id2 + m_size1 * m_size3 * id3; - return (*itr)(); + return (BaseType *)(*itr)(); } private: diff --git a/src/Core/Mpl.h b/src/Core/Mpl.h index 0fbf83d..6d2dd3c 100644 --- a/src/Core/Mpl.h +++ b/src/Core/Mpl.h @@ -56,6 +56,9 @@ #include + + + /** * Max size of nofold inerited capability */ diff --git a/src/Core/testing/CMakeLists.txt b/src/Core/testing/CMakeLists.txt index 236c4f1..50c3a3d 100644 --- a/src/Core/testing/CMakeLists.txt +++ b/src/Core/testing/CMakeLists.txt @@ -24,6 +24,7 @@ set( TESTS ProgrammableAccessorTest ClassFactoryTest MplSequenceCombinerTest + ClassCompoundTest ) set(LIBRARIES diff --git a/src/Core/testing/ClassCompoundTest.cpp b/src/Core/testing/ClassCompoundTest.cpp new file mode 100644 index 0000000..a1f4a8f --- /dev/null +++ b/src/Core/testing/ClassCompoundTest.cpp @@ -0,0 +1,215 @@ +/*////////////////////////////////////////////////////////////////////////////// +// CMT Cosmic Muon Tomography project ////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + + Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova + All rights reserved + + Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > + + ------------------------------------------------------------------ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. + +//////////////////////////////////////////////////////////////////////////////*/ + +#include + +#include "Core/Vector.h" +#include "Core/ClassCompound.h" + +#include "testing-prototype.h" + +using namespace uLib; + + + +//////////////////////////////////////////////////////////////////////////////// +// WORKING EXAMPLE // + +namespace Test { + + +class Voxel { +public: + virtual void Set(float) = 0; + virtual float Get() const = 0; + virtual ~Voxel() {} +}; + +class VoxelMean : public Voxel { +public: + VoxelMean() : m_data(0), m_count(0) {} + void Set(float data) { m_data += data; ++m_count; } + float Get() const { return m_data / m_count; } +private: + float m_data; + int m_count; +}; + +class VoxelVal : public Voxel { +public: + VoxelVal() : m_data(0) {} + void Set(float data) { m_data = data; } + float Get() const { return m_data; } +private: + float m_data; +}; + + + + +class VoxCount { +public: + template < class T > + int Count(const Vector &ref ) const { + return ref.size(); + } +}; + +class VoxCountOver { +public: + VoxCountOver() : m_threshold(0) {} + + template < class T > + int Count(const Vector &ref ) const { + int count = 0 ; + foreach (const T &el, ref) { + if( el.Get() >= m_threshold ) ++count; + } + return count; + } + float m_threshold; +}; + + + + +class VoxelVectorBase { +public: + virtual float Get(int) const = 0; + virtual void Set(int,float) = 0; + virtual int Size() const = 0; + virtual int Count() const = 0; + virtual ~VoxelVectorBase() {} +}; + +template < class T > +void copy(T *src, T *dst) { } + +void copy(VoxelVectorBase *src, VoxelVectorBase *dst) { + for(int i=0; iSize(); ++i) { + dst->Set(i,src->Get(i)); + } +} + + +template < class VoxType, + class CounterType > +class VoxelVector : + public VoxelVectorBase, + public ClassCompound< VoxType, CounterType > +{ + typedef ClassCompound< VoxType, CounterType > Compound; + +public: + + VoxelVector() {} + + template < class Other > + VoxelVector(const Other &t) : Compound(t) { + // assumes that Other is a voxelvector // + for(int i=0; iSet(i, t.Get(i)); + } + } + + template < class Other > + VoxelVector & operator = (const Other &t) { + for(int i=0; iSet(i, t.Get(i)); + } + (Compound &)(*this) = t; + return *this; + } + + using Compound::operator =; + + float Get(int id) const { return m_data[id].Get(); } + void Set(int id, float data) { + if(id >= Size()) m_data.resize(id+1); + m_data[id].Set(data); + } + int Size() const { return m_data.size(); } + int Count() const { + return CounterType::Count(m_data); + } +private: + friend class VoxelVectorFactory; + Vector m_data; +}; + + +} // Test + + +using namespace Test; + + + +int main() { + + VoxelVector< VoxelMean, VoxCountOver > img; + img.Set(0,555); + img.Set(1,23); + img.Set(1,25); + img.Set(2,68); + + img.A1::m_threshold = 50; + + std::cout << "-> "; + for(int i=0; i<3; ++i) { + std::cout << img.Get(i) << " "; + } + std::cout << " count: " << img.Count() << "\n"; + + + VoxelVector< VoxelVal, VoxCountOver > img2 = img; + + img2.Set(1,0); + + std::cout << "-> "; + for(int i=0; i<3; ++i) { + std::cout << img2.Get(i) << " "; + } + std::cout << " count threshold: " << img2.A1::m_threshold << " "; + std::cout << " count: " << img2.Count() << "\n"; + + + +} + + + + + + + + + + + + + + + diff --git a/src/Core/testing/ClassFactoryTest.cpp b/src/Core/testing/ClassFactoryTest.cpp index 48d9b9c..63c9e25 100644 --- a/src/Core/testing/ClassFactoryTest.cpp +++ b/src/Core/testing/ClassFactoryTest.cpp @@ -24,133 +24,23 @@ //////////////////////////////////////////////////////////////////////////////*/ #include + +//#include "boost/preprocessor.hpp" +//#include "boost/preprocessor/repetition.hpp" + #include "Core/MplSequenceCombiner.h" + +#include "Core/ClassCompound.h" + #include "Core/ClassFactory.h" #include "Core/Serializable.h" - - #include "testing-prototype.h" using namespace uLib; - - - - - - - - - - - - - - - - - -//namespace { -class Base { -public: - Base() {} - Base(const Base ©) {} - - virtual void Go() {} -}; - -class Derived : public Base { -public: - void Go() { std::cout << "Derived Go\n"; } -}; - -class Derived2 : public Base { -public: - void Go() { std::cout << "Derived2 Go\n"; } -}; - -class Derived3 : public Base { -public: - void Go() { std::cout << "Derived3 Go\n"; } -}; - -class Derived4 : public Base { -public: - void Go() { std::cout << "Derived4 Go\n"; } -}; - - -template < - class A1, - class A2 - > -class AlgHolder : public Base { - A1 m_a1; - A2 m_a2; -public: - void Go() { - std::cout << "AlgHolder Go: \n"; - std::cout << " A1 -> "; m_a1.Go(); - std::cout << " A2 -> "; m_a2.Go(); - } -}; - -//} - - - - - -typedef mpl::vector< Derived, Derived2, Derived3, Derived4 > seq; - - -class ProgrammableAlgHolder { -public: - ProgrammableAlgHolder() : m_id1(0), m_id2(0) - { m_base = m_factory.Create(0,0); } - - template < typename T > - void SetA1(const T *alg = NULL) { - int id = m_factory.FindS1(); - Base * newbase = m_factory.Create(id,m_id2); - *newbase = *m_base; - delete m_base; - m_base = newbase; - } - - template < typename T > - void SetA2(const T *alg = NULL) { - int id = m_factory.FindS2(); - Base * newbase = m_factory.Create(m_id1,id); - *newbase = *m_base; - delete m_base; - m_base = newbase; - } - - Base * operator -> () { return m_base; } - -private: - RegisteredClassFactory2 m_factory; - int m_id1, m_id2; - Base * m_base; -}; - - - -//int main() { -// ProgrammableAlgHolder ah; -// ah.SetA1(); -// ah->Go(); - -// return 0; -//} - - - - //////////////////////////////////////////////////////////////////////////////// // WORKING EXAMPLE // @@ -190,7 +80,7 @@ private: class VoxCount { public: template < class T > - int Count(const Vector &ref ) { + int Count(const Vector &ref ) const { return ref.size(); } }; @@ -200,7 +90,7 @@ public: VoxCountOver() : m_threshold(0) {} template < class T > - int Count(const Vector &ref ) { + int Count(const Vector &ref ) const { int count = 0 ; foreach (const T &el, ref) { if( el.Get() >= m_threshold ) ++count; @@ -236,6 +126,16 @@ template < class VoxType, class CounterType > class VoxelVector : public VoxelVectorBase { public: + + VoxelVector() {} // remove? + VoxelVector( const VoxType *A1, const CounterType *A2 ) { + (void) A1; + SetA2(A2); + } + + void * GetA2() { return &m_counter; } + void SetA2(const void *A2) { m_counter = *A2; } + float Get(int id) const { return m_data[id].Get(); } void Set(int id, float data) { if(id >= Size()) m_data.resize(id+1); @@ -250,11 +150,18 @@ private: }; - - class VoxelVectorFactory { public: - VoxelVectorFactory() : m_id1(0), m_id2(0) { m_base = m_factory.Create(0,0); } + VoxelVectorFactory() : + m_id1(0), m_id2(0) + { + m_base = m_factory.Create(0,0); + } + + ~VoxelVectorFactory() { + delete m_base; + } + VoxelVectorBase * operator -> () const { return m_base; } template < typename T > @@ -262,6 +169,9 @@ public: int id = m_factory.FindS1(); VoxelVectorBase * newbase = m_factory.Create(id,m_id2); Test::copy(m_base,newbase); // *newbase = *m_base; + + // + delete m_base; m_base = newbase; } @@ -271,7 +181,9 @@ public: int id = m_factory.FindS2(); VoxelVectorBase * newbase = m_factory.Create(m_id1,id); Test::copy(m_base,newbase); // *newbase = *m_base; - // ????? come copiare i membri ???? //// + + // + delete m_base; m_base = newbase; } @@ -289,22 +201,41 @@ private: + +struct B1 { + B1() : m_b1(1) {} + int m_b1; +}; + +struct B2 { + B2() : m_b2(2) {} + int m_b2; +}; + +struct B3 { + B3() : m_b3(3) {} + int m_b3; +}; + +struct B3b { + B3b() : m_b3(3) {} + int m_b3; // learn to handle ambiguity .. +}; + + int main() { - Test::VoxelVectorFactory factory; - for(int i=0; i<10; ++i) - factory->Set(i,i); - - factory.SetVoxel(); - - for(int i=0; i<10; ++i) - std::cout << factory->Get(i) << " "; - std::cout << "\n"; - - std::cout << "vox count = " << factory->Count() << "\n"; + ClassCompound< B1, B2 > h1; + ClassCompound< B2, B3, B1 > h2; + h1.A0::m_b1 = 111; + h1.A1::m_b2 = 222; + h2 = h1; + + std::cout << "h1: " << h1.A0::m_b1 << " " << h1.A1::m_b2 << "\n"; + std::cout << "h2: " << h2.A0::m_b2 << " " << h2.A1::m_b3 << "\n"; }