Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » U++ Library support » U++ Core » NEW: generic Toupel grouper
NEW: generic Toupel grouper [message #27972] Thu, 12 August 2010 16:03 Go to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
sometimes its cool to group things together in an easy manner, especially when wroking with the template containers. to build a grouping container over and over again each time for different purposes, just for classes that would have the parts public anyway,is odd.

say you want to have a vector that simply contains a 2-tupel of values. maybe some measurements consisting of two values at once, or anything that logically belongs together but does not need any abstraction or scope hiding. a normal container cant do it.

Vector<float, float> vi; //would resemble VectorMap.


you just need to quickly define and access 2 things at once in a container and want to have sth like
Vector<Duo<int, int> > vi;
...
vi[i].t1 = 123;
vi[i].t2 = 234;

this looks good and is handy.

so here comes some helpers to do that

template<class T>
class Solo
{
public:
	typedef Solo<T> CLASSNAME;
	Solo(const T & _t) : t(_t) {}
	Solo() {}

	operator T & () { return t; }
	operator const T & () const { return t; }
	
	T t;
};

template<class T1, class T2>
class Duo
{
public:
	typedef Duo<T1, T2> CLASSNAME;
	Duo(const T1 & _t1, const T2 & _t2) : t1(_t1), t2(_t2) {}
	Duo() {}

	operator T1 & () { return t1; }
	operator const T1 & () const { return t1; }
	operator T2 & () { return t2; }
	operator const T2 & () const { return t2; }
	
	T1 t1;
	T2 t2;
};

template<class T1, class T2, class T3>
class Trio
{
public:
	typedef Trio<T1, T2, T3> CLASSNAME;
	Trio(const T1 & _t1, const T2 & _t2, const T3 & _t3) : t1(_t1), t2(_t2), t3(_t3) {}
	Trio() {}

	operator T1 & () { return t1; }
	operator const T1 & () const { return t1; }
	operator T2 & () { return t2; }
	operator const T2 & () const { return t2; }
	operator T3 & () { return t3; }
	operator const T3 & () const { return t3; }
	
	T1 t1;
	T2 t2;
	T3 t3;
};

template<class T1, class T2, class T3, class T4>
class Quartett
{
public:
	typedef Quartett<T1, T2, T3, T4> CLASSNAME;
	Quartett(const T1 & _t1, const T2 & _t2, const T3 & _t3, const T4 & _t4) : t1(_t1), t2(_t2), t3(_t3), t4(_t4) {}
	Quartett() {}

	operator T1 & () { return t1; }
	operator const T1 & () const { return t1; }
	operator T2 & () { return t2; }
	operator const T2 & () const { return t2; }
	operator T3 & () { return t3; }
	operator const T3 & () const { return t3; }
	operator T4 & () { return t4; }
	operator const T4 & () const { return t4; }
	
	T1 t1;
	T2 t2;
	T3 t3;
	T4 t4;
};

maybe they can go to Others.h..
Re: NEW: generic Toupel grouper [message #27974 is a reply to message #27972] Thu, 12 August 2010 16:07 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
or, which would be better maybe, to have Two<T1, T2>, Three<T1,T2,T3>, Four<T1,T2,T3,T4> as analoge to One<T>..

but sometimes that much of complexity is not needed
Re: NEW: generic Toupel grouper [message #27976 is a reply to message #27974] Thu, 12 August 2010 16:14 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3357
Registered: August 2008
Senior Veteran
Hello Kohait

This does not seem bad. However is it worthwhile the added code to support it?, as we always can insert in a Vector any class or struct.


Best regards
Iñaki
Re: NEW: generic Toupel grouper [message #27978 is a reply to message #27976] Thu, 12 August 2010 16:58 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
ofcorse..but imagine, you need to setup a new class each time you simply just want to group/pack some things together without further class implications / namespaces / accessscopes. i imagine this to be quite often the case. (Point_ is not quite the same but is a small example of grouping things)

but here comes another option, which is maybe better...donnow.

template<class T>
class O
{
public:
	typedef O<T> CLASSNAME;
	O(const T & _t) : t(_t) {}
	O() {}

	operator T & () { return t; }
	operator const T & () const { return t; }

	T t;
};

template<class T>
class O1 : public O<T> {};

template<class T1, class T2>
class O2 : public O<T1>, public O<T2> {};

template<class T1, class T2, class T3>
class O3 : public O<T1>, public O<T2>, public O<T3> {};

template<class T1, class T2, class T3, class T4>
class O4 : public O<T1>, public O<T2> , public O<T3> , public O<T4> {};


beeing able to access stuff like this, which is more clear
	O2<int, float> o2;
	
	o2.O<int>::t = 123;
	o2.O<float>::t = 23.10f;

[Updated on: Thu, 12 August 2010 17:03]

Report message to a moderator

Re: NEW: generic Toupel grouper [message #27979 is a reply to message #27978] Thu, 12 August 2010 17:03 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3357
Registered: August 2008
Senior Veteran
Shocked -> Smile

Best regards
Iñaki
Re: NEW: generic Toupel grouper [message #27980 is a reply to message #27979] Thu, 12 August 2010 17:04 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
even got another idea..

template<class T1, class T2>
class Two : public One<T1>, public One<T2> {};

template<class T1, class T2, class T3>
class Three : public One<T1>, public One<T2>, public One<T3> {};

template<class T1, class T2, class T3, class T4>
class Four : public One<T1>, public One<T2>, public One<T3>, public One<T4> {};

EDIT: too quick Smile forgot a type

	Four<int, char, float, unsigned> four;
	four.One<int>::Create() = 123;

[Updated on: Thu, 12 August 2010 17:20]

Report message to a moderator

Re: NEW: generic Toupel grouper [message #27982 is a reply to message #27980] Thu, 12 August 2010 17:27 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
a bit more usable Smile
template<class T>
class O
{
public:
	typedef O<T> CLASSNAME;
	O(const T & _t) : t(_t) {}
	O() {}

	operator T & () { return t; }
	operator const T & () const { return t; }
	
	T& operator=(const T & _t) { t = _t; return t; }
	bool operator ==(const T& _t) const { return (t==_t); }
	
	T t;
};
Re: NEW: generic Toupel grouper [message #27985 is a reply to message #27982] Thu, 12 August 2010 20:14 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

Hi kohait00,

I've got two questions Wink

1) Does it work when you need to group several values of same type? E.g. Three<String,int,int>. I have a suspicion that the overloaded operators for int wouldn't make much sense than...

2) What is the advantage of your touples to using simple Vector<Value>? The later might have bit more verbose interface, but on the other hand it offers variable element count.

Best regards,
Honza
Re: NEW: generic Toupel grouper [message #27986 is a reply to message #27985] Thu, 12 August 2010 20:58 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
hey doli, you are absolutely right with your point 1)
but in this case Duo<int,int> work, becasue there the items are named explicitely.

de advantage is, that zou dont always want to store all data inside Value, but as an explicit tzype.

but using same tzpe one might think of using Duo<String, Vector<int> >, grouping it Smile

it is still a development, so expect some changes here. but the idea is to loosely group stuff together without the need to create a whole new class for it.. its maybe considred a class template, instead of a template class. a public members class.

cheers
Re: NEW: generic Toupel grouper [message #28015 is a reply to message #27986] Fri, 13 August 2010 10:53 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Actually, I think this feature is somewhat missing in U++ (and is quite common in other frameworks).

But I am quite sceptical about those cast overloads too.

Imo, something as simple as

template<class T1, class T2>
struct Pair {
Pair(const T1 & _t1, const T2 & _t2) : t1(_t1), t2(_t2) {}
Pair() {}

T1 first;
T2 second;
};

would solve most of usage scenarios where I was eventually missing tuples.

Maybe first/second are bad names though...

Hm, maybe, what about

template<class T1, class T2>
struct AB {
AB(const T1 & _t1, const T2 & _t2) : t1(_t1), t2(_t2) {}
AB() {}

T1 a;
T2 b;
};

? Smile

Here is boost's take on the issue:

http://www.boost.org/doc/libs/1_34_0/libs/tuple/doc/tuple_us ers_guide.html

IMO a little bit overengineered...
Re: NEW: generic Toupel grouper [message #28017 is a reply to message #28015] Fri, 13 August 2010 10:58 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
simple is most times better Smile

good option. maybe AB, ABC is not 'verbose' enough (as of readability of code, but tfcorse a short option)

Re: NEW: generic Toupel grouper [message #28026 is a reply to message #28017] Fri, 13 August 2010 11:16 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
Quote:


But I am quite sceptical about those cast overloads too.


its just for easy handling, while opening doors to implicit casted assigns to wrong parameter (dont know if compiler would warn in such case, which operator() to take)

can be left out i think. if user uses it, he can type some 2 more letters and be on safe side. if he really needs this behaviour, polimophism is a good thing..
Re: NEW: generic Toupel grouper [message #28037 is a reply to message #28026] Fri, 13 August 2010 14:59 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
i found AB, ABC etc. beeing difficult to use, because wingdi.h already defines ABC. Confused

ive looked into the boost stuff, it's really a bit over the line.
beeing on the secure side and type one letter is cool enough..

so this is a proposal, short enough not to blow Others.h

template<class T1, class T2>
class Duo
{
public:
	Duo(const T1 & _a, const T2 & _b) : a(_a), b(_b) {}
	Duo() {}
	T1 a; T2 b;
};

template<class T1, class T2, class T3>
class Trio
{
public:
	Trio(const T1 & _a, const T2 & _b, const T3 & _c) : a(_a), b(_b), c(_c) {}
	Trio() {}
	T1 a; T2 b; T3 c;
};

template<class T1, class T2, class T3, class T4>
class Quartett
{
public:
	Quartett(const T1 & _a, const T2 & _b, const T3 & _c, const T4 & _d) : a(_a), b(_b), c(_c), d(_d) {}
	Quartett() {}
	T1 a; T2 b; T3 c; T4 d;
};

[Updated on: Fri, 13 August 2010 14:59]

Report message to a moderator

Re: NEW: generic Toupel grouper [message #28053 is a reply to message #28037] Fri, 13 August 2010 20:21 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

The boost implementation is really overkill. But one thing I like about it is the "indexed" access using the get<N>() function.

Also, something like
//for Two (similar for bigger touples):
	Value operator[](int i)const{
		ASSERT(i>=0&&i<2);
		if(i==0) return a;
		else return b;
	}
would be nice thing to have.

Honza
Re: NEW: generic Toupel grouper [message #28058 is a reply to message #27972] Sat, 14 August 2010 01:40 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

So, after criticizing kohaits proposals I felt obligated to show my own idea about how Touples should be implemented... Here is the result:
#include <Core/Core.h>
using namespace Upp;

String AsString(Nuller n){return "";}

template <int N,class A,class B,class C> struct TTypes          {typedef Nuller Type;};
template <class A,class B,class C>       struct TTypes<0,A,B,C> {typedef A Type;};
template <class A,class B,class C>       struct TTypes<1,A,B,C> {typedef B Type;};
template <class A,class B,class C>       struct TTypes<2,A,B,C> {typedef C Type;};

template<class A, class B,class C> struct Touple;

template<int N,class A,class B,class C> struct Retriever{
	static Nuller Get(Touple<A,B,C>& t){return Null;};
};
template<class A,class B,class C> struct Retriever<0,A,B,C>{
	static typename TTypes<0,A,B,C>::Type Get(Touple<A,B,C>& t){return t.a;};
};
template<class A,class B,class C> struct Retriever<1,A,B,C>{
	static typename TTypes<1,A,B,C>::Type Get(Touple<A,B,C>& t){return t.b;};
};
template<class A,class B,class C> struct Retriever<2,A,B,C>{
	static typename TTypes<2,A,B,C>::Type Get(Touple<A,B,C>& t){return t.c;};
};

template<class A, class B=Nuller,class C=Nuller>
struct Touple{
	A a;
	B b;
	C c;
	Touple(){};
	Touple(A a):a(a){};
	Touple(A a,B b):a(a),b(b){};
	Touple(A a,B b,C c):a(a),b(b),c(c){};
	
	template<int N>
	typename TTypes<N,A,B,C>::Type Get(){
		return Retriever<N,A,B,C>::Get(*this);
	};
	template<class T>
	Touple& operator=(const T& t){
		a=t.a; b=t.b; c=t.c;
	}
	int GetCount()const{
		for(int i=2; i>0; i--){
			if((*this)[i]!=Value(Null)) return i+1;
		}
		return 1;
	}
	Value operator[](int i)const{
		if     (i==0) return Value(a);
		else if(i==1) return Value(b);
		else if(i==2) return Value(c);
		else ASSERT_(false,"index out of bounds");
	}
	String ToString()const{
		String s=AsString(c);
		s=AsString(b)+(s.GetLength()>0?",":"")+s;
		s=AsString(a)+(s.GetLength()>0?",":"")+s;
		return "{"+s+"}";
	}
};

template<class A>
Touple<A> Solo(const A& a){
	return Touple<A>(a);
};

template<class A,class B>
Touple<A,B> Duo(const A& a,const B& b){
	return Touple<A,B>(a,b);
};

template<class A,class B,class C>
Touple<A,B,C> Trio(const A& a,const B& b,const C& c){
	return Touple<A,B,C>(a,b,c);
};

CONSOLE_APP_MAIN{
	Touple<double,const char*> s;
	Touple<int,String> t;
	Touple<int,String,double> u;
	
	t.a=1; t.b="test";
	DUMP(t.Get<0>()); DUMP(t.Get<1>());
	for(int i=0; i<t.GetCount(); i++){
		LOG(i<<": "<<t[i]);
	}
	s=t;                             DUMP(s);
	t=Duo(1,String("hello world"));  DUMP(t);
	u=t;                             DUMP(u);
	u.c=3.2;                         DUMP(u);
	// <double>=<triple> fails to compile:
	// t=Triple(1,String("dsd"),3);  DUMP(t);
}


The main difference is that there is no specific type for two,three, etc. values, but rather a single Touple class that can be used universally. The implementation above allows 1,2 or 3 elements, but can be easily extended. The main idea is that smaller touple can be assigned into bigger (extra elements are Null), while bigger into smaller triggers compilation errors. The functions Solo,Duo and Trio are supposed to save you some typing by generating the touples based on the arguments types. The only thing I found missing in Core was AsString(Nuller) which should be no problem to add.

The ideas from my previous post are included. I am aware that touple.Get<0>() doesn't have any significant syntactic value, since it is the same as touple.a, but it might help the readability a bit. On the other hand, the operator[] is quite important, since it allows iterating through the Touple. TEven though it returns Values, together with GetCount() (returning number of elements from 0 to last non-Null) should be quite powerfull tool.

What do you think?

Honza

PS: The Solo,Duo and Trio names were chosen just because there already is One and Single. Otherwise I would prefer Single, Double, etc.
Re: NEW: generic Toupel grouper [message #28064 is a reply to message #28053] Sat, 14 August 2010 11:53 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
dolik.rce wrote on Fri, 13 August 2010 14:21

The boost implementation is really overkill. But one thing I like about it is the "indexed" access using the get<N>() function.

Also, something like
//for Two (similar for bigger touples):
	Value operator[](int i)const{
		ASSERT(i>=0&&i<2);
		if(i==0) return a;
		else return b;
	}
would be nice thing to have.

Honza


You expect too much about types involved here IMO.
Re: NEW: generic Toupel grouper [message #28066 is a reply to message #28064] Sat, 14 August 2010 12:25 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

luzr wrote on Sat, 14 August 2010 11:53

dolik.rce wrote on Fri, 13 August 2010 14:21

The boost implementation is really overkill. But one thing I like about it is the "indexed" access using the get<N>() function.

Also, something like
//for Two (similar for bigger touples):
	Value operator[](int i)const{
		ASSERT(i>=0&&i<2);
		if(i==0) return a;
		else return b;
	}
would be nice thing to have.

Honza


You expect too much about types involved here IMO.

I am aware of that. But if I am not mistaken, it doesn't affect functionality of the class too much. The compilation should fail only in case when the operator is actually used, since it is templated. If user knows the type is not compatible, he will just have to resort back to using the members directly. There should be no or minimal performance penalty for that... Am I right?

Moreover, there are some further assumption made anyway, about compatibility with Null. That might be even more restricting...

Honza
Re: NEW: generic Toupel grouper [message #28091 is a reply to message #28058] Sun, 15 August 2010 09:16 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
Quote:


Otherwise I would prefer Single, Double, etc.


there, similarities to data types wouled be to close (Double) and misleading. Solo is not usefull anyway (wraping one T is .. nonsense), it should start with Duo, Trio, etc.. to set Apart from the One (and maybe later Two, Three)

Quote:


after criticizing kohaits proposals


dont worry, it's part of development, and didnt feel criticised Smile. i am always looking forward to meeting better ideas..

to the above implementation:

the Get<1>() option (idea from boost?) is a cool trick, but IMHO of little use because it's not a runtime check, but a compile time definition, thus u.a, u.b, u.c is much simpler and clearer in that sense, and less to type anyway. i mean, in terms of compile time specialisation u.Get<1> is same as u.a, you have to provide the index at compiletime, so you know which type.

the Value operator[](int i) is a good idea though. to wrap / unwrap in value (boxing / unboxing is used in C# and others, though there in different context, as base class object).

having Duo, Trio, etc is, as you pointed out, more or less useless, even if it's better to read Smile so i added a 5th T and deaulted past second T. (i'd rater use EmptyClass, but there is no Value(const EmptyClass &) for it, so i used Nuller. might be usefull to have an EmptyClass Value as well?)

so here comes another option.

template<class T1, class T2, class T3=Nuller, class T4=Nuller, class T5=Nuller>
class Tupel
{
public:
	Tupel(const T1 & _a, const T2 & _b, const T3 & _c, const T4 & _d, const T5 & _e) 
		: a(_a), b(_b), c(_c), d(_d), e(_e) {}
	Tupel() {}

	Value operator[](int i) {
		switch(i) {
			case 1: return Value(a);	
			case 2: return Value(b);	
			case 3: return Value(c);	
			case 4: return Value(d);	
			case 5: return Value(e);	
			default:
			case 0: ASSERT(0); return Value();	
		}
		return Value(); //dummy
	}

	T1 a; T2 b; T3 c; T4 d; T5 e;
};


what about this one? it provides the simplicity desired and has the wrapper.

Re: NEW: generic Toupel grouper [message #28092 is a reply to message #28091] Sun, 15 August 2010 13:09 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

Hi Kohait

kohait00 wrote on Sun, 15 August 2010 09:16

dont worry, it's part of development, and didnt feel criticised Smile. i am always looking forward to meeting better ideas..

I don't worry, it was a joke Wink

kohait00 wrote on Sun, 15 August 2010 09:16


the Get<1>() option (idea from boost?) is a cool trick, but IMHO of little use because it's not a runtime check, but a compile time definition, thus u.a, u.b, u.c is much simpler and clearer in that sense, and less to type anyway. i mean, in terms of compile time specialisation u.Get<1> is same as u.a, you have to provide the index at compiletime, so you know which type.

Yes, it is from boost. As I said, it is mostly useless and the only way it might be helpful is making the code look better and hopefully better readable. But I don't insist on having it at all. At least it learned me some interesting new things about templates Smile

kohait00 wrote on Sun, 15 August 2010 09:16


the Value operator[](int i) is a good idea though. to wrap / unwrap in value (boxing / unboxing is used in C# and others, though there in different context, as base class object).

Don't forget about the GetCount() too Wink I just don't like my implementation of it very much, but I can't come up with anything better. And if possible I would also like to see Begin() and End() implemented, so I could do DUMPC(touple)...

kohait00 wrote on Sun, 15 August 2010 09:16


having Duo, Trio, etc is, as you pointed out, more or less useless, even if it's better to read Smile so i added a 5th T and deaulted past second T. (i'd rater use EmptyClass, but there is no Value(const EmptyClass &) for it, so i used Nuller. might be usefull to have an EmptyClass Value as well?)

I would strongly prefer EmptyClass too. But there might be idealogical problem: Once you make it value compatible, it won't be empty any more Smile Maybe we should do a special class for this purpose, let's say DummyElement, which would be Value and Null compatible.

Apart from what I said above, especially the missing GetCount(), your last code seems reasonable. Definitely not that difficult to read as mine Smile (which is good)

Honza

[Updated on: Sun, 15 August 2010 13:10]

Report message to a moderator

Re: NEW: generic Toupel grouper [message #28128 is a reply to message #28092] Tue, 17 August 2010 22:22 Go to previous messageGo to previous message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
Quote:


learned me some interesting new things about templates


i'm always looking to learn as well Smile

Quote:


Don't forget about the GetCount()


i dont think that it is that much of use either. becasue everything is know at compiletime, and Tupel is not meant to be a base class. so i cant imagine any practicle usecase. i'd prefer to, as mirek statet, have it as simple as possible, and serve its due as beeing a compile time known simple strong type container / grouper of data types. not more nor less, except there is more things to have on it, that are of real use.

EmptyClass would be great, but..your point is really good. it wouldnt be empty. but thinking of Nuller as base class in that field is ok too. actually it is a logical requirement, when enabling the Value wrapping of the types. so it's not that tragic.

what do you guys think? is there more to add to this one?
should i add it to bazaar or will it join Others.h?

(I'm trying to 'empty' my development nest, which in time has grown with some little things maybe usefull)
Previous Topic: Date limited to 2020 and 2015 does not work ?!?
Next Topic: Value question (memory consumption)
Goto Forum:
  


Current Time: Sat Apr 27 19:57:03 CEST 2024

Total time taken to generate the page: 0.06125 seconds