From dd13aa342fe2054132bba2c72ff1399401d8dade Mon Sep 17 00:00:00 2001 From: AndreaRigoni Date: Thu, 30 Jul 2015 18:39:20 +0200 Subject: [PATCH] adds ClassComposite idiom --- src/Core/CMakeLists.txt | 1 + src/Core/ClassComposite.h | 240 ++++++++++++++++++++++++ src/Core/ClassCompound.h | 10 +- src/Core/testing/CMakeLists.txt | 2 + src/Core/testing/ClassCompositeTest.cpp | 73 +++++++ src/Core/testing/ClassCompoundTest.cpp | 3 - src/Core/testing/ClassCompoundTest2.cpp | 193 +++++++++++++++++++ uLib.files | 5 +- uLib.includes | 2 +- 9 files changed, 519 insertions(+), 10 deletions(-) create mode 100644 src/Core/ClassComposite.h create mode 100644 src/Core/testing/ClassCompositeTest.cpp create mode 100644 src/Core/testing/ClassCompoundTest2.cpp diff --git a/src/Core/CMakeLists.txt b/src/Core/CMakeLists.txt index e051f6c..21229c4 100644 --- a/src/Core/CMakeLists.txt +++ b/src/Core/CMakeLists.txt @@ -25,6 +25,7 @@ set(HEADERS Named.h MplSequenceCombiner.h ClassCompound.h + ClassComposite.h ) SET(SOURCES diff --git a/src/Core/ClassComposite.h b/src/Core/ClassComposite.h new file mode 100644 index 0000000..4798361 --- /dev/null +++ b/src/Core/ClassComposite.h @@ -0,0 +1,240 @@ +#ifndef CLASSCOMPOSITE_H +#define CLASSCOMPOSITE_H + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +namespace uLib { +namespace detail { + + +template < typename _Seq > +struct ClassComposite { + typedef _Seq Seq; + + //////////////////////////////////////////////////////////////////////////////// + // TUPLE ///////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + + template + struct tuple_push_front; + + template + struct tuple_push_front > { + typedef boost::tuple type; + }; + + // TUPLE // + typedef typename boost::mpl::reverse_copy< Seq, + boost::mpl::inserter, + tuple_push_front > + >::type + Tuple; + + + //////////////////////////////////////////////////////////////////////////////// + // COPY ////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + // Copy operator structure // + template < typename Other > + struct CopyOp { + const Other &m_other; + ClassComposite * const m_this; + + CopyOp(const Other &other, ClassComposite * const src) : m_other(other), m_this(src) {} + + template < typename U > + void operator () (U) const { + static const int id = mpl::at< U, mpl::int_<2> >::type::value; + boost::tuples::get(m_this->m_tuple) = boost::tuples::get(m_other.m_tuple); + } + }; + + template < class Other > + inline void copy ( const Other © ) throw () { + // sequence of type pairs + typedef typename mpl::zip_view< mpl::vector >::type zip; + + // adds position to each element + typedef typename mpl::range_c::value >::type range; + typedef typename mpl::zip_view< mpl::vector >::type zip_range; + + // filter only elements that match + typedef typename mpl::filter_view< zip_range, + boost::is_same< mpl::at< mpl::_ , mpl::int_<0> >, + mpl::at< mpl::_ , mpl::int_<1> > + > + >::type filtered_zip; + // apply copy + mpl::for_each(CopyOp(copy,this)); + } + + + ClassComposite() {} + + template < class Other > + ClassComposite(const Other ©) { + this->copy(copy); + } + + template < class Other > + const ClassComposite & operator = (const Other ©) { + this->copy(copy); + return *this; + } + + template < int n, class A > + ClassComposite< typename mpl::replace_el::type > + SetComponent(const A &alg) { + typedef typename mpl::replace_el::type _seq; + ClassComposite< _seq > out = *this; + boost::tuples::get(out) = alg; + return out; + } + + + Tuple m_tuple; +}; + + + +} // detail + + +struct Null {}; +template < typename T0 = Null, + typename T1 = Null, + typename T2 = Null, + typename T3 = Null, + typename T4 = Null, + typename T5 = Null > +class ClassComposite : detail::ClassComposite< mpl::vector<> > { +public: + typedef detail::ClassComposite< mpl::vector<> > BaseClass; + + T0& A0(); + T1& A1(); + T2& A2(); + T3& A3(); + T4& A4(); + T5& A5(); + + using BaseClass::operator =; + using BaseClass::SetComponent; + +private: + // NOT ACCESSIBLE because never reached // + ClassComposite() {} + + template < class Other > + ClassComposite(const Other &t) : BaseClass(t) {} +}; + + + + +template < typename _A0 > +class ClassComposite<_A0> : public detail::ClassComposite< mpl::vector<_A0> > +{ + typedef detail::ClassComposite< mpl::vector<_A0> > BaseClass; +public: + ClassComposite() {} + + ClassComposite(const _A0 &a0) : + BaseClass::m_tuple(a0) + {} + + template < typename Other > + ClassComposite(const Other ©) : BaseClass(copy) {} + + _A0& A0() { return boost::tuples::get<0>(this->m_tuple); } + const _A0& A0() const { return boost::tuples::get<0>(this->m_tuple); } + + using BaseClass::operator =; + using BaseClass::SetComponent; +}; + + + + +template < typename _A0, typename _A1 > +class ClassComposite<_A0,_A1> : public detail::ClassComposite< mpl::vector<_A0,_A1> > +{ + typedef detail::ClassComposite< mpl::vector<_A0,_A1> > BaseClass; +public: + ClassComposite() {} + + ClassComposite(const _A0 &a0, const _A1 &a1) : + BaseClass::m_tuple(a0,a1) + {} + + template < typename Other > + ClassComposite(const Other ©) : BaseClass(copy) {} + + _A0& A0() { return boost::tuples::get<0>(this->m_tuple); } + _A1& A1() { return boost::tuples::get<1>(this->m_tuple); } + const _A0& A0() const { return boost::tuples::get<0>(this->m_tuple); } + const _A1& A1() const { return boost::tuples::get<1>(this->m_tuple); } + + using BaseClass::operator =; + using BaseClass::SetComponent; +}; + + + + +template < typename _A0, typename _A1, typename _A2 > +class ClassComposite<_A0,_A1,_A2> : public detail::ClassComposite< mpl::vector<_A0,_A1,_A2> > +{ + typedef detail::ClassComposite< mpl::vector<_A0,_A1,_A2> > BaseClass; +public: + ClassComposite() {} + + ClassComposite(const _A0 &a0, const _A1 &a1, const _A2 &a2) : + BaseClass::m_tuple(a0,a1,a2) + {} + + template < typename Other > + ClassComposite(const Other ©) : BaseClass(copy) {} + + _A0& A0() { return boost::tuples::get<0>(this->m_tuple); } + _A1& A1() { return boost::tuples::get<1>(this->m_tuple); } + _A2& A2() { return boost::tuples::get<2>(this->m_tuple); } + const _A0& A0() const { return boost::tuples::get<0>(this->m_tuple); } + const _A1& A1() const { return boost::tuples::get<1>(this->m_tuple); } + const _A2& A2() const { return boost::tuples::get<2>(this->m_tuple); } + + using BaseClass::operator =; + using BaseClass::SetComponent; +}; + +// TODO: add more Ax ... + + +} // uLib + + + +#endif // CLASSCOMPOSITE_H + diff --git a/src/Core/ClassCompound.h b/src/Core/ClassCompound.h index c9f688d..074f191 100644 --- a/src/Core/ClassCompound.h +++ b/src/Core/ClassCompound.h @@ -22,7 +22,7 @@ struct ClassCompound : ULIB_MPL_INHERIT_SEQ(_Seq) { template < class S > struct CopyOp { - CopyOp(const S * src, ClassCompound * const dst) : m_src(src), m_dst(dst) {} + 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 { @@ -38,24 +38,24 @@ struct ClassCompound : ULIB_MPL_INHERIT_SEQ(_Seq) { template < class A > void operator()(A) const { - const A &t = *m_src; + const A &t = m_src; copy(t, boost::is_base_of()); } ClassCompound * const m_dst; - const S *m_src; + const S& m_src; }; template < class Other > ClassCompound(const Other ©) { typedef typename Other::Seq _seq; - mpl::for_each<_seq>(CopyOp(©,this)); + mpl::for_each<_seq>(CopyOp(copy,this)); } template < class Other > inline void copy ( const Other © ) throw () { typedef typename Other::Seq _seq; - mpl::for_each<_seq>(CopyOp(©,this)); + mpl::for_each<_seq>(CopyOp(copy,this)); } template < class Other > diff --git a/src/Core/testing/CMakeLists.txt b/src/Core/testing/CMakeLists.txt index fdee5aa..4a0aff2 100644 --- a/src/Core/testing/CMakeLists.txt +++ b/src/Core/testing/CMakeLists.txt @@ -26,7 +26,9 @@ set( TESTS ClassFactoryRuntimeTest MplSequenceCombinerTest ClassCompoundTest + ClassCompoundTest2 MplSequenceReplaceElTest + ClassCompositeTest ) set(LIBRARIES diff --git a/src/Core/testing/ClassCompositeTest.cpp b/src/Core/testing/ClassCompositeTest.cpp new file mode 100644 index 0000000..9926ceb --- /dev/null +++ b/src/Core/testing/ClassCompositeTest.cpp @@ -0,0 +1,73 @@ +/*////////////////////////////////////////////////////////////////////////////// +// 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/ClassComposite.h" +#include "Core/StaticInterface.h" +#include "Core/Mpl.h" +#include "Core/Types.h" +#include "testing-prototype.h" + +using namespace uLib; + + + +struct Voxel { + int a; + float b; +}; + + + +int main(int argc, char *argv[]) +{ + BEGIN_TESTING(ClassComposite); + + Voxel v1 = { 1, 2 }; + Voxel v2 = { 555, 2368 }; + + ClassComposite p1; + ClassComposite p2; + ClassComposite p3; + + p1.A0() = 0; + p1.A1() = 555.2368; + + p2.A0() = v2; + p2.A1() = 0; + + p2.copy(p1); + TEST1( p1.A1() == p2.A1() ); + + p3.A0() = v1; + p3 = p2; + + std::cout << p2.A0().a << " " << p2.A0().b << "\n"; + + + END_TESTING; +} diff --git a/src/Core/testing/ClassCompoundTest.cpp b/src/Core/testing/ClassCompoundTest.cpp index cf774c1..96cfa49 100644 --- a/src/Core/testing/ClassCompoundTest.cpp +++ b/src/Core/testing/ClassCompoundTest.cpp @@ -258,9 +258,6 @@ int main() { - - - VoxelVector< Vector, VoxCountOver > img2; img2 = img; diff --git a/src/Core/testing/ClassCompoundTest2.cpp b/src/Core/testing/ClassCompoundTest2.cpp new file mode 100644 index 0000000..f835ab9 --- /dev/null +++ b/src/Core/testing/ClassCompoundTest2.cpp @@ -0,0 +1,193 @@ +/*////////////////////////////////////////////////////////////////////////////// +// 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 "Core/StaticInterface.h" +#include "Core/Mpl.h" + +#include "testing-prototype.h" + +using namespace uLib; + +// This test aims to define a voxel collection object to test the connection +// with an external counter algorithm. The VoxCollection is set from a Voxel +// definition and the Counter should automatically arange to match it. +// + + +namespace Test { + +class VoxelInterface { + void * m_ob; + float (* m_Get)(void * const); + void (* m_Set)(void * const, float data); + template static float s_Get(void * const ob) { return static_cast(ob)->Get(); } + template static void s_Set(void * const ob, float data) { static_cast(ob)->Set(data); } +public: + template + VoxelInterface( T& t) : + m_ob(&t), + m_Get(&s_Get), + m_Set(&s_Set) + {} + float Get() { return (*m_Get)(m_ob); } + void Set(float data) { (*m_Set)(m_ob,data); } +}; + + + +class Voxel { +public: + Voxel() : m_data(0) {} + void Set(float data) { m_data = data; } + float Get() const { return m_data; } +private: + float m_data; +}; + +class VoxelMean { +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 Counter { +public: + template < typename V > + int Count (const V &cnt) const { + return cnt.size(); + } +}; + +class CountOverTh { +public: + template < typename V > + int Count (const V &cnt) const { + int count = 0; + foreach (const typename V::value_type &el, cnt) + if(el.Get() > m_threshold) count++; + return count; + } + float m_threshold; +}; + + + +class VoxelVectorBase { +public: + virtual ~VoxelVectorBase() {} + virtual int Count() const = 0; + + template < class T0, class T1 > + static VoxelVectorBase * New( const T0 &t0, const T1 &t1); + +}; + +template < class _V, class _C > +class VoxelVector : + public VoxelVectorBase, + public ClassCompound< _V, _C > +{ + typedef ClassCompound< _V, _C > Compound; +public: + typedef _V Data; + typedef _C Counter; + + VoxelVector() {} + + template < class Other > + VoxelVector(const Other ©) : Compound(copy) {} + + using Compound::operator =; + + int Count() const { return this->A1().Count(this->A0()); } +}; + + +template < class T0, class T1 > +VoxelVectorBase *VoxelVectorBase::New(const T0 &t0, const T1 &t1) +{ + VoxelVector *out = new VoxelVector; + // ULIB_INTERFACE_ASSERT(VoxCountInterface,T1); + out->A0() = t0; + out->A1() = t1; + return out; +} + + + +} // Test + + + + + +using namespace Test; + +int main(int argc, char *argv[]) +{ + BEGIN_TESTING(Class Compound Test2); + + VoxelVector, Counter> v; + std::cout << v.Count() << "\n"; + + v.Data::push_back(Voxel()); + v.Data::back().Set(0.555); + std::cout << v.Count() << " - value = " << v.Data::back().Get() << "\n"; + + VoxelVector, CountOverTh> v2 = v; + v2.Counter::m_threshold = 1; + std::cout << v2.Count() << " - value = " << v2.Data::back().Get() << "\n"; + + + VoxelVector< Vector, CountOverTh> v3 = v2; + v3.Data::push_back(VoxelMean()); + v3.Data::back().Set(0.555); + std::cout << v3.Count() << " - value = " << v3.Data::back().Get() << "\n"; + + VoxelVector< Vector, Counter> v4 = v3.SetComponent<1>(Counter()); + std::cout << v4.Count() << " - value = " << v4.Data::back().Get() << "\n"; + + + CountOverTh c; + c.m_threshold = 0.6; + VoxelVectorBase *v5 = VoxelVectorBase::New(v4.A0(),c); + std::cout << v5->Count() << "\n"; + delete v5; + + END_TESTING; +} + diff --git a/uLib.files b/uLib.files index 30191c9..ca84601 100644 --- a/uLib.files +++ b/uLib.files @@ -527,4 +527,7 @@ test.cpp ulib.h uLibConfig.cmake.in uLibConfigVersion.cmake.in -vtk_test.cpp \ No newline at end of file +vtk_test.cpp +src/Core/testing/ClassCompoundTest2.cpp +src/Core/ClassComposite.h +src/Core/testing/ClassCompositeTest.cpp diff --git a/uLib.includes b/uLib.includes index 97a6bd5..c81da07 100644 --- a/uLib.includes +++ b/uLib.includes @@ -18,4 +18,4 @@ src/Root src/utils/moc src/Vtk src/Vtk/testing -tmp/c_vtable \ No newline at end of file +tmp/c_vtable