adds ClassComposite idiom

This commit is contained in:
AndreaRigoni
2015-07-30 18:39:20 +02:00
parent fe6d8e9e4e
commit dd13aa342f
9 changed files with 519 additions and 10 deletions

View File

@@ -25,6 +25,7 @@ set(HEADERS
Named.h
MplSequenceCombiner.h
ClassCompound.h
ClassComposite.h
)
SET(SOURCES

240
src/Core/ClassComposite.h Normal file
View File

@@ -0,0 +1,240 @@
#ifndef CLASSCOMPOSITE_H
#define CLASSCOMPOSITE_H
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/mpl/zip_view.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/at.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/same_as.hpp>
#include <Core/Types.h>
#include <Core/Mpl.h>
namespace uLib {
namespace detail {
template < typename _Seq >
struct ClassComposite {
typedef _Seq Seq;
////////////////////////////////////////////////////////////////////////////////
// TUPLE /////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
template<class T, class Tuple>
struct tuple_push_front;
template<class T, BOOST_PP_ENUM_PARAMS(10, class T)>
struct tuple_push_front<T, boost::tuple<BOOST_PP_ENUM_PARAMS(10, T)> > {
typedef boost::tuple<T, BOOST_PP_ENUM_PARAMS(9, T)> type;
};
// TUPLE //
typedef typename boost::mpl::reverse_copy< Seq,
boost::mpl::inserter<boost::tuple<>,
tuple_push_front<boost::mpl::_2, boost::mpl::_1> >
>::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<id>(m_this->m_tuple) = boost::tuples::get<id>(m_other.m_tuple);
}
};
template < class Other >
inline void copy ( const Other &copy ) throw () {
// sequence of type pairs
typedef typename mpl::zip_view< mpl::vector<Seq, typename Other::Seq> >::type zip;
// adds position to each element
typedef typename mpl::range_c<int, 0, mpl::size<zip>::value >::type range;
typedef typename mpl::zip_view< mpl::vector<Seq, typename Other::Seq, range> >::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<filtered_zip>(CopyOp<Other>(copy,this));
}
ClassComposite() {}
template < class Other >
ClassComposite(const Other &copy) {
this->copy(copy);
}
template < class Other >
const ClassComposite & operator = (const Other &copy) {
this->copy(copy);
return *this;
}
template < int n, class A >
ClassComposite< typename mpl::replace_el<Seq,A,n>::type >
SetComponent(const A &alg) {
typedef typename mpl::replace_el<Seq,A,n>::type _seq;
ClassComposite< _seq > out = *this;
boost::tuples::get<n>(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 &copy) : 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 &copy) : 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 &copy) : 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

View File

@@ -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<bool,b>&) 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<A,ClassCompound>());
}
ClassCompound * const m_dst;
const S *m_src;
const S& m_src;
};
template < class Other >
ClassCompound(const Other &copy) {
typedef typename Other::Seq _seq;
mpl::for_each<_seq>(CopyOp<Other>(&copy,this));
mpl::for_each<_seq>(CopyOp<Other>(copy,this));
}
template < class Other >
inline void copy ( const Other &copy ) throw () {
typedef typename Other::Seq _seq;
mpl::for_each<_seq>(CopyOp<Other>(&copy,this));
mpl::for_each<_seq>(CopyOp<Other>(copy,this));
}
template < class Other >

View File

@@ -26,7 +26,9 @@ set( TESTS
ClassFactoryRuntimeTest
MplSequenceCombinerTest
ClassCompoundTest
ClassCompoundTest2
MplSequenceReplaceElTest
ClassCompositeTest
)
set(LIBRARIES

View File

@@ -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 <iostream>
#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<int,float> p1;
ClassComposite<Voxel, float> p2;
ClassComposite<Voxel, float> 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;
}

View File

@@ -258,9 +258,6 @@ int main() {
VoxelVector< Vector<VoxelVal>, VoxCountOver > img2;
img2 = img;

View File

@@ -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 <iostream>
#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 <typename T> static float s_Get(void * const ob) { return static_cast<T*>(ob)->Get(); }
template <typename T> static void s_Set(void * const ob, float data) { static_cast<T*>(ob)->Set(data); }
public:
template <typename T>
VoxelInterface( T& t) :
m_ob(&t),
m_Get(&s_Get<T>),
m_Set(&s_Set<T>)
{}
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 &copy) : 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<T0,T1> *out = new VoxelVector<T0,T1>;
// 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<Vector<Voxel>, 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<Vector<Voxel>, CountOverTh> v2 = v;
v2.Counter::m_threshold = 1;
std::cout << v2.Count() << " - value = " << v2.Data::back().Get() << "\n";
VoxelVector< Vector<VoxelMean>, 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<VoxelMean>, 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;
}

View File

@@ -528,3 +528,6 @@ ulib.h
uLibConfig.cmake.in
uLibConfigVersion.cmake.in
vtk_test.cpp
src/Core/testing/ClassCompoundTest2.cpp
src/Core/ClassComposite.h
src/Core/testing/ClassCompositeTest.cpp