This commit is contained in:
Christian Zimmermann 2017-12-17 14:16:37 +01:00
parent f38b675314
commit a3acfedd9b
4 changed files with 249 additions and 219 deletions

View file

@ -30,20 +30,17 @@ namespace MultiArrayTools
private: private:
friend IB;
bool mExternControl = false; bool mExternControl = false;
IndexPack mIPack; IndexPack mIPack;
std::array<size_t,sizeof...(Indices)+1> mBlockSizes; std::array<size_t,sizeof...(Indices)+1> mBlockSizes;
public: public:
ContainerIndex() = delete; ContainerIndex() = delete;
template <class MRange> template <class MRange>
ContainerIndex(const std::shared_ptr<MRange>& range); ContainerIndex(const std::shared_ptr<MRange>& range);
ContainerIndex& operator=(size_t pos) { IB::operator=(pos) ; return *this; }
template <size_t N> template <size_t N>
auto get() const -> decltype( *std::get<N>( mIPack ) )&; auto get() const -> decltype( *std::get<N>( mIPack ) )&;
@ -54,130 +51,36 @@ namespace MultiArrayTools
ContainerIndex& operator()(const std::shared_ptr<Indices>&... inds); // control via external indices ContainerIndex& operator()(const std::shared_ptr<Indices>&... inds); // control via external indices
ContainerIndex& operator()(); // -> sync; just to shorten the code ContainerIndex& operator()(); // -> sync; just to shorten the code
std::shared_ptr<RangeType> range() const { return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr ); }
private:
//ContainerIndex(const ContainerIndex& in);
//ContainerIndex& operator=(const ContainerIndex& in);
// ==== >>>>> STATIC POLYMORPHISM <<<<< ==== // ==== >>>>> STATIC POLYMORPHISM <<<<< ====
static IndexType S_type(ContainerIndex const* i) { return IndexType::CONT; } IndexType type();
static ContainerIndex& S_pp_op(ContainerIndex* i) ContainerIndex& operator++();
{ ContainerIndex& operator--();
if(i->mExternControl){
i->mPos = PackNum<sizeof...(Indices)-1>::makePos(i->mIPack);
}
PackNum<sizeof...(Indices)-1>::pp( i->mIPack );
++i->mPos;
return *i;
}
static ContainerIndex& S_mm_op(ContainerIndex* i) ContainerIndex& operator=(size_t pos);
{
if(i->mExternControl){
i->mPos = PackNum<sizeof...(Indices)-1>::makePos(i->mIPack);
}
PackNum<sizeof...(Indices)-1>::mm( i->mIPack );
--i->mPos;
return *i;
} int pp(std::intptr_t idxPtrNum);
int mm(std::intptr_t idxPtrNum);
static ContainerIndex& S_ass_op(ContainerIndex* i, size_t pos) MetaType meta();
{ ContainerIndex& at(const MetaType& metaPos);
i->mPos = pos;
PackNum<sizeof...(Indices)-1>::setIndexPack(i->mIPack, pos);
return *i;
}
static int S_pp(ContainerIndex* i, std::intptr_t idxPtrNum) size_t dim();
{ bool first();
int tmp = PackNum<sizeof...(Indices)-1>::pp(i->mIPack, i->mBlockSizes, idxPtrNum); bool last();
i->mPos += tmp;
return tmp;
}
static int S_mm(ContainerIndex* i, std::intptr_t idxPtrNum) std::shared_ptr<RangeType> range();
{
int tmp = PackNum<sizeof...(Indices)-1>::mm(i->mIPack, i->mBlockSizes, idxPtrNum);
i->mPos -= tmp;
return tmp;
}
static MetaType S_meta(ContainerIndex const* i)
{
MetaType metaTuple;
PackNum<sizeof...(Indices)-1>::getMetaPos(metaTuple, i->mIPack);
return metaTuple;
}
static ContainerIndex& S_at(ContainerIndex* i, const MetaType& metaPos)
{
PackNum<sizeof...(Indices)-1>::setMeta(i->mIPack, metaPos);
i->mPos = PackNum<sizeof...(Indices)-1>::makePos(i->mIPack);
return *i;
}
static size_t S_dim(ContainerIndex const* i)
{
return sizeof...(Indices);
}
static bool S_first(ContainerIndex const* i)
{
return i->pos() == 0;
}
static bool S_last(ContainerIndex const* i)
{
return i->pos() == i->mMax - 1;
}
static std::shared_ptr<RangeType> S_range(ContainerIndex const* i)
{
return std::dynamic_pointer_cast<RangeType>( i->mRangePtr );
}
template <size_t N> template <size_t N>
static auto S_getPtr(ContainerIndex const* i) -> decltype( std::get<N>( mIPack ) )& auto getPtr() -> decltype( std::get<N>( mIPack ) )&;
{
return std::get<N>( i->mIPack );
}
static std::shared_ptr<VIWB> S_getVPtr(ContainerIndex const* i, size_t n) std::shared_ptr<VIWB> getVPtr(size_t n);
{ size_t getStepSize(size_t n);
if(n >= sizeof...(Indices)){
assert(0);
// throw !!
}
ContainerIndex<Indices...> const* t = i;
return PackNum<sizeof...(Indices)-1>::getIndexPtr(*t, n);
}
static size_t S_getStepSize(ContainerIndex const* i, size_t n) std::string id();
{ void print(size_t offset);
if(n >= sizeof...(Indices)){
assert(0);
// throw !!
}
return i->mBlockSizes[n+1];
}
static std::string S_id(ContainerIndex const* i) { return std::string("con") + std::to_string(i->mId); }
static void S_print(ContainerIndex const* i, size_t offset)
{
if(offset == 0){
std::cout << " === " << std::endl;
}
for(size_t j = 0; j != offset; ++j) { std::cout << "\t"; }
std::cout << S_id(i) << "[" << reinterpret_cast<std::intptr_t>(i) << "]"
<< "(" << i->mRangePtr << "): " << S_meta(i) << std::endl;
PackNum<sizeof...(Indices)-1>::printIndex(i->mIPack, offset+1);
}
}; };
@ -310,6 +213,144 @@ namespace MultiArrayTools
return sync(); return sync();
} }
template <class... Indices>
IndexType ContainerIndex<Indices...>::type() { return IndexType::CONT; }
template <class... Indices>
ContainerIndex<Indices...>& ContainerIndex<Indices...>::operator++()
{
if(mExternControl){
IB::mPos = PackNum<sizeof...(Indices)-1>::makePos(mIPack);
}
PackNum<sizeof...(Indices)-1>::pp( mIPack );
++IB::mPos;
return *this;
}
template <class... Indices>
ContainerIndex<Indices...>& ContainerIndex<Indices...>::operator--()
{
if(mExternControl){
IB::mPos = PackNum<sizeof...(Indices)-1>::makePos(mIPack);
}
PackNum<sizeof...(Indices)-1>::mm( mIPack );
--IB::mPos;
return *this;
}
template <class... Indices>
ContainerIndex<Indices...>& ContainerIndex<Indices...>::operator=(size_t pos)
{
IB::mPos = pos;
PackNum<sizeof...(Indices)-1>::setIndexPack(mIPack, pos);
return *this;
}
template <class... Indices>
int ContainerIndex<Indices...>::pp(std::intptr_t idxPtrNum)
{
int tmp = PackNum<sizeof...(Indices)-1>::pp(mIPack, mBlockSizes, idxPtrNum);
IB::mPos += tmp;
return tmp;
}
template <class... Indices>
int ContainerIndex<Indices...>::mm(std::intptr_t idxPtrNum)
{
int tmp = PackNum<sizeof...(Indices)-1>::mm(mIPack, mBlockSizes, idxPtrNum);
IB::mPos -= tmp;
return tmp;
}
template <class... Indices>
typename ContainerIndex<Indices...>::MetaType ContainerIndex<Indices...>::meta()
{
MetaType metaTuple;
PackNum<sizeof...(Indices)-1>::getMetaPos(metaTuple, mIPack);
return metaTuple;
}
template <class... Indices>
ContainerIndex<Indices...>& ContainerIndex<Indices...>::at(const MetaType& metaPos)
{
PackNum<sizeof...(Indices)-1>::setMeta(mIPack, metaPos);
IB::mPos = PackNum<sizeof...(Indices)-1>::makePos(mIPack);
return *this;
}
template <class... Indices>
size_t ContainerIndex<Indices...>::dim()
{
return sizeof...(Indices);
}
template <class... Indices>
bool ContainerIndex<Indices...>::first()
{
return IB::pos() == 0;
}
template <class... Indices>
bool ContainerIndex<Indices...>::last()
{
return IB::pos() == IB::mMax - 1;
}
template <class... Indices>
std::shared_ptr<typename ContainerIndex<Indices...>::RangeType>
ContainerIndex<Indices...>::range()
{
return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr );
}
template <class... Indices>
template <size_t N>
auto ContainerIndex<Indices...>::getPtr() -> decltype( std::get<N>( mIPack ) )&
{
return std::get<N>( mIPack );
}
template <class... Indices>
std::shared_ptr<VIWB> ContainerIndex<Indices...>::getVPtr(size_t n)
{
if(n >= sizeof...(Indices)){
assert(0);
// throw !!
}
ContainerIndex<Indices...> const* t = this;
return PackNum<sizeof...(Indices)-1>::getIndexPtr(*t, n);
}
template <class... Indices>
size_t ContainerIndex<Indices...>::getStepSize(size_t n)
{
if(n >= sizeof...(Indices)){
assert(0);
// throw !!
}
return mBlockSizes[n+1];
}
template <class... Indices>
std::string ContainerIndex<Indices...>::id()
{
return std::string("con") + std::to_string(IB::mId);
}
template <class... Indices>
void ContainerIndex<Indices...>::print(size_t offset)
{
if(offset == 0){
std::cout << " === " << std::endl;
}
for(size_t j = 0; j != offset; ++j) { std::cout << "\t"; }
std::cout << id() << "[" << reinterpret_cast<std::intptr_t>(this) << "]"
<< "(" << IB::mRangePtr << "): " << meta() << std::endl;
PackNum<sizeof...(Indices)-1>::printIndex(mIPack, offset+1);
}
/***************************** /*****************************
* ContainerRangeFactory * * ContainerRangeFactory *
*****************************/ *****************************/

View file

@ -85,29 +85,29 @@ namespace MultiArrayTools
//DEFAULT_MEMBERS(IndexInterface); //DEFAULT_MEMBERS(IndexInterface);
I* THIS() { return static_cast<I*>(this); } I& THIS() { return static_cast<I&>(*this); }
I const* THIS() const { return static_cast<I const*>(this); } I const& THIS() const { return static_cast<I const&>(*this); }
~IndexInterface() = default; ~IndexInterface() = default;
IndexType type() const { return I::S_type(THIS()); } IndexType type() const { return THIS().type(); }
I& operator=(size_t pos) { return I::S_ass_op(THIS(), pos); } I& operator=(size_t pos) { return THIS() = pos; }
I& operator++() { return I::S_pp_op(THIS()); } I& operator++() { return THIS()++; }
I& operator--() { return I::S_mm_op(THIS()); } I& operator--() { return THIS()--;}
int pp(std::intptr_t idxPtrNum) { return I::S_pp(THIS(), idxPtrNum); } int pp(std::intptr_t idxPtrNum) { return THIS().pp(idxPtrNum); }
int mm(std::intptr_t idxPtrNum) { return I::S_mm(THIS(), idxPtrNum); } int mm(std::intptr_t idxPtrNum) { return THIS().mm(idxPtrNum); }
bool operator==(const IndexInterface& in) const; bool operator==(const IndexInterface& in) const;
bool operator!=(const IndexInterface& in) const; bool operator!=(const IndexInterface& in) const;
size_t dim() const { return I::S_dim(THIS()); } size_t dim() const { return THIS().dim(); }
size_t pos() const; size_t pos() const;
size_t max() const; size_t max() const;
bool last() const { return I::S_last(THIS()); } bool last() const { return THIS().last(); }
bool first() const { return I::S_first(THIS()); } bool first() const { return THIS().first(); }
std::shared_ptr<RangeBase> vrange() const { return mRangePtr; } std::shared_ptr<RangeBase> vrange() const { return mRangePtr; }
@ -117,18 +117,18 @@ namespace MultiArrayTools
auto getPtr() const -> decltype(I::template S_get<N>(THIS())) auto getPtr() const -> decltype(I::template S_get<N>(THIS()))
{ return I::template S_get<N>(THIS()); } { return I::template S_get<N>(THIS()); }
*/ */
std::shared_ptr<VIWB> getVPtr(size_t n) const { return I::S_getVPtr(THIS(),n); } std::shared_ptr<VIWB> getVPtr(size_t n) const { return THIS().getVPtr(n); }
size_t getStepSize(size_t n) const { return I::S_getStepSize(THIS(),n); } size_t getStepSize(size_t n) const { return THIS().getStepSize(n); }
operator size_t() const; operator size_t() const;
std::string id() const { return I::S_id(THIS()); } std::string id() const { return THIS().id(); }
MetaType meta() const { return I::S_meta(THIS()); } MetaType meta() const { return THIS().meta(); }
I& at(const MetaType& meta) { return I::S_at(THIS(), meta); } I& at(const MetaType& meta) { return THIS().at(meta); }
void print(size_t offset = 0) const { I::S_print(THIS(), offset); } void print(size_t offset = 0) const { THIS().print(offset); }
private: private:

View file

@ -41,8 +41,6 @@ namespace MultiArrayTools
MultiIndex() = delete; MultiIndex() = delete;
MultiIndex& operator=(size_t pos) { IB::operator=(pos) ; return *this; }
// NO DEFAULT HERE !!! // NO DEFAULT HERE !!!
// ( have to assign sub-indices (ptr!) correctly ) // ( have to assign sub-indices (ptr!) correctly )
//MultiIndex(const MultiIndex& in); //MultiIndex(const MultiIndex& in);
@ -72,119 +70,116 @@ namespace MultiArrayTools
std::shared_ptr<RangeType> range() const { return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr ); } std::shared_ptr<RangeType> range() const { return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr ); }
private:
friend IB;
// ==== >>>>> STATIC POLYMORPHISM <<<<< ==== // ==== >>>>> STATIC POLYMORPHISM <<<<< ====
static IndexType S_type(MultiIndex const* i) { return IndexType::MULTI; } IndexType type() { return IndexType::MULTI; }
static MultiIndex& S_ass_op(MultiIndex* i, size_t pos) MultiIndex& operator=(size_t pos)
{ {
i->mPos = pos; IB::mPos = pos;
PackNum<sizeof...(Indices)-1>::setIndexPack(i->mIPack, pos); PackNum<sizeof...(Indices)-1>::setIndexPack(mIPack, pos);
return *i; return *this;
} }
static MultiIndex& S_pp_op(MultiIndex* i) MultiIndex& operator++()
{ {
PackNum<sizeof...(Indices)-1>::pp( i->mIPack ); PackNum<sizeof...(Indices)-1>::pp( mIPack );
++i->mPos; ++IB::mPos;
return *i; return *this;
} }
static MultiIndex& S_mm_op(MultiIndex* i) MultiIndex& operator--()
{ {
PackNum<sizeof...(Indices)-1>::mm( i->mIPack ); PackNum<sizeof...(Indices)-1>::mm( mIPack );
--i->mPos; --IB::mPos;
return *i; return *this;
} }
static int S_pp(MultiIndex* i, std::intptr_t idxPtrNum) int pp(std::intptr_t idxPtrNum)
{ {
int tmp = PackNum<sizeof...(Indices)-1>::pp(i->mIPack, i->mBlockSizes, idxPtrNum); int tmp = PackNum<sizeof...(Indices)-1>::pp(mIPack, mBlockSizes, idxPtrNum);
i->mPos += tmp; IB::mPos += tmp;
return tmp; return tmp;
} }
static int S_mm(MultiIndex* i, std::intptr_t idxPtrNum) int mm(std::intptr_t idxPtrNum)
{ {
int tmp = PackNum<sizeof...(Indices)-1>::mm(i->mIPack, i->mBlockSizes, idxPtrNum); int tmp = PackNum<sizeof...(Indices)-1>::mm(mIPack, mBlockSizes, idxPtrNum);
i->mPos -= tmp; IB::mPos -= tmp;
return tmp; return tmp;
} }
static MetaType S_meta(MultiIndex const* i) MetaType meta()
{ {
MetaType metaTuple; MetaType metaTuple;
PackNum<sizeof...(Indices)-1>::getMetaPos(metaTuple, i->mIPack); PackNum<sizeof...(Indices)-1>::getMetaPos(metaTuple, mIPack);
return metaTuple; return metaTuple;
} }
static MultiIndex& S_at(MultiIndex* i, const MetaType& metaPos) MultiIndex& at(const MetaType& metaPos)
{ {
PackNum<sizeof...(Indices)-1>::setMeta(i->mIPack, metaPos); PackNum<sizeof...(Indices)-1>::setMeta(mIPack, metaPos);
i->mPos = PackNum<sizeof...(Indices)-1>::makePos(i->mIPack); IB::mPos = PackNum<sizeof...(Indices)-1>::makePos(mIPack);
return *i; return *this;
} }
static size_t S_dim(MultiIndex const* i) size_t dim()
{ {
return sizeof...(Indices); return sizeof...(Indices);
} }
static bool S_first(MultiIndex const* i) bool first()
{ {
return i->mPos == 0; return IB::mPos == 0;
} }
static bool S_last(MultiIndex const* i) bool last()
{ {
return i->mPos == i->mMax - 1; return IB::mPos == IB::mMax - 1;
} }
static std::shared_ptr<RangeType> S_range(MultiIndex const* i) std::shared_ptr<RangeType> range()
{ {
return std::dynamic_pointer_cast<RangeType>( i->mRangePtr ); return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr );
} }
template <size_t N> template <size_t N>
static auto S_getPtr(MultiIndex const* i) -> decltype( std::get<N>( mIPack ) )& auto getPtr() -> decltype( std::get<N>( mIPack ) )&
{ {
return std::get<N>(i->mIPack); return std::get<N>(mIPack);
} }
//const IndexBase& get(size_t n); //const IndexBase& get(size_t n);
static std::shared_ptr<VIWB> S_getVPtr(MultiIndex const* i, size_t n) std::shared_ptr<VIWB> getVPtr(size_t n)
{ {
if(n >= sizeof...(Indices)){ if(n >= sizeof...(Indices)){
assert(0); assert(0);
// throw !! // throw !!
} }
MultiIndex<Indices...> const* t = i; MultiIndex<Indices...> const* t = this;
return PackNum<sizeof...(Indices)-1>::getIndexPtr(*t, n); return PackNum<sizeof...(Indices)-1>::getIndexPtr(*t, n);
} }
static size_t S_getStepSize(MultiIndex const* i, size_t n) size_t getStepSize(size_t n)
{ {
if(n >= sizeof...(Indices)){ if(n >= sizeof...(Indices)){
assert(0); assert(0);
// throw !! // throw !!
} }
return i->mBlockSizes[n+1]; return mBlockSizes[n+1];
} }
static std::string S_id(MultiIndex const* i) { return std::string("mul") + std::to_string(i->mId); } std::string id() { return std::string("mul") + std::to_string(IB::mId); }
static void S_print(MultiIndex const* i, size_t offset) void print(size_t offset)
{ {
if(offset == 0){ if(offset == 0){
std::cout << " === " << std::endl; std::cout << " === " << std::endl;
} }
for(size_t j = 0; j != offset; ++j) { std::cout << "\t"; } for(size_t j = 0; j != offset; ++j) { std::cout << "\t"; }
std::cout << S_id(i) << "[" << reinterpret_cast<std::intptr_t>(i) std::cout << id() << "[" << reinterpret_cast<std::intptr_t>(this)
<< "]" << "(" << i->mRangePtr << "): " << S_meta(i) << std::endl; << "]" << "(" << IB::mRangePtr << "): " << meta() << std::endl;
PackNum<sizeof...(Indices)-1>::printIndex(i->mIPack, offset+1); PackNum<sizeof...(Indices)-1>::printIndex(mIPack, offset+1);
} }
}; };

View file

@ -27,105 +27,99 @@ namespace MultiArrayTools
SingleIndex(const std::shared_ptr<SingleRange<U,TYPE> >& range); SingleIndex(const std::shared_ptr<SingleRange<U,TYPE> >& range);
SingleIndex& operator=(size_t pos) { IB::operator=(pos); return *this; }
std::shared_ptr<RangeType> range() const { return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr ); } std::shared_ptr<RangeType> range() const { return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr ); }
private:
friend IB;
// ==== >>>>> STATIC POLYMORPHISM <<<<< ==== // ==== >>>>> STATIC POLYMORPHISM <<<<< ====
static IndexType S_type(SingleIndex const* i) IndexType type()
{ {
return IndexType::SINGLE; return IndexType::SINGLE;
} }
static SingleIndex& S_ass_op(SingleIndex* i, size_t pos) SingleIndex& operator=(size_t pos)
{ {
i->mPos = pos; IB::mPos = pos;
return *i; return *this;
} }
static SingleIndex& S_pp_op(SingleIndex* i) SingleIndex& operator++()
{ {
++i->mPos; ++IB::mPos;
return *i; return *this;
} }
static SingleIndex& S_mm_op(SingleIndex* i) SingleIndex& operator--()
{ {
--i->mPos; --IB::mPos;
return *i; return *this;
} }
static int S_pp(SingleIndex* i, std::intptr_t idxPtrNum) int pp(std::intptr_t idxPtrNum)
{ {
++(*i); ++(*this);
return 1; return 1;
} }
static int S_mm(SingleIndex* i, std::intptr_t idxPtrNum) int mm(std::intptr_t idxPtrNum)
{ {
--(*i); --(*this);
return 1; return 1;
} }
static U S_meta(SingleIndex const* i) U meta()
{ {
return std::dynamic_pointer_cast<SingleRange<U,TYPE> const>( i->mRangePtr )->get( i->pos() ); return std::dynamic_pointer_cast<SingleRange<U,TYPE> const>( IB::mRangePtr )->get( IB::pos() );
} }
static SingleIndex& S_at(SingleIndex* i, const U& metaPos) SingleIndex& at(const U& metaPos)
{ {
(*i) = std::dynamic_pointer_cast<SingleRange<U,TYPE> const>( i->mRangePtr )->getMeta( metaPos ); (*this) = std::dynamic_pointer_cast<SingleRange<U,TYPE> const>( IB::mRangePtr )->getMeta( metaPos );
return *i; return *this;
} }
static size_t S_dim(SingleIndex const* i) // = 1 size_t dim() // = 1
{ {
return 1; return 1;
} }
static bool S_last(SingleIndex const* i) bool last()
{ {
return i->mPos == i->mMax - 1; return IB::mPos == IB::mMax - 1;
} }
static bool S_first(SingleIndex const* i) bool first()
{ {
return i->mPos == 0; return IB::mPos == 0;
} }
static std::shared_ptr<RangeType> S_range(SingleIndex const* i) std::shared_ptr<RangeType> range()
{ {
return std::dynamic_pointer_cast<RangeType>( i->mRangePtr ); return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr );
} }
template <size_t N> template <size_t N>
static void S_getPtr(SingleIndex* i) {} void getPtr() {}
static std::shared_ptr<VIWB> S_getVPtr(SingleIndex const* i, size_t n) std::shared_ptr<VIWB> getVPtr(size_t n)
{ {
return std::shared_ptr<VIWB>(); return std::shared_ptr<VIWB>();
} }
static size_t S_getStepSize(SingleIndex const* i, size_t n) size_t getStepSize(size_t n)
{ {
return 1; return 1;
} }
static std::string S_id(SingleIndex const* i) { return std::string("sin") + std::to_string(i->mId); } std::string id() { return std::string("sin") + std::to_string(IB::mId); }
static void S_print(SingleIndex const* i, size_t offset) void print(size_t offset)
{ {
if(offset == 0){ if(offset == 0){
std::cout << " === " << std::endl; std::cout << " === " << std::endl;
} }
for(size_t j = 0; j != offset; ++j) { std::cout << "\t"; } for(size_t j = 0; j != offset; ++j) { std::cout << "\t"; }
std::cout << S_id(i) << "[" << reinterpret_cast<std::intptr_t>(i) std::cout << id() << "[" << reinterpret_cast<std::intptr_t>(this)
<< "](" << i->mRangePtr << "): " << S_meta(i) << std::endl; << "](" << IB::mRangePtr << "): " << meta() << std::endl;
} }
}; };