By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,413 Members | 998 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,413 IT Pros & Developers. It's quick & easy.

Template question

P: n/a
Hi all,

I have a question which is illustrated by the following piece of code:

template <class T>
class A {
T my_value;
};

In a list, I'd like to store pointers to objects of class A. But I don't
know at forehand if these will be A<intor A<doubleor whatever (all
these flavours of A must be stored in the same list). And, lateron if I
retrieve the objects from the list I may have to know what flavour the
object was in order to call the proper routines for processing them.

My question: what does the list look like in C++? I'm lost, so if anyone
has some advice....

Thanks,

Jeroen
Mar 6 '07 #1
Share this Question
Share on Google+
16 Replies


P: n/a
Jeroen wrote:
Hi all,

I have a question which is illustrated by the following piece of code:

template <class T>
class A {
T my_value;
};

In a list, I'd like to store pointers to objects of class A. But I don't
know at forehand if these will be A<intor A<doubleor whatever (all
these flavours of A must be stored in the same list). And, lateron if I
retrieve the objects from the list I may have to know what flavour the
object was in order to call the proper routines for processing them.

My question: what does the list look like in C++? I'm lost, so if anyone
has some advice....

Thanks,

Jeroen
You need to store all different types in the same list? And later you
need to recover what was the type of object stored in the list?

Sorry but in C++ that can't be done.

john
Mar 6 '07 #2

P: n/a
Jeroen wrote:
I have a question which is illustrated by the following piece of code:

template <class T>
class A {
T my_value;
};

In a list,
What's the definition of your 'list'?
I'd like to store pointers to objects of class A.
There is no "class A" until you define what the template argument is.
There is only "class template A".
But I
don't know at forehand if these will be A<intor A<doubleor
whatever (all these flavours of A must be stored in the same list).
There is no such thing as "flavour" in C++. Here you talk about what
is known as "instantiations" of the same template. They are _different_
*types*. Objects of different types cannot be stored in the same
container (unless you define your container in some very tricky and
special way). So, what's the definition of your 'list'?
And, lateron if I retrieve the objects from the list I may have to
know what flavour the object was in order to call the proper routines
for processing them.
My question: what does the list look like in C++? I'm lost, so if
anyone has some advice....
What problem are you trying to solve? It is very likely that you
need a "heterogeneous container". Look it up. But it's impossible
to advise anything given such vague "problem definition".

Also read the FAQ. What you seem to describe here is usually solved
through polymorphism (and it's not all that difficult). But you did
not say what kind of "processing" you are going to do, nor does your
class template 'A' have any functionality, which begs the question,
why don't you just store 'ints' and 'doubles' in your 'list'?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask`
Mar 6 '07 #3

P: n/a
John Harrison wrote:
Jeroen wrote:
>Hi all,

I have a question which is illustrated by the following piece of
code: template <class T>
class A {
T my_value;
};

In a list, I'd like to store pointers to objects of class A. But I
don't know at forehand if these will be A<intor A<doubleor
whatever (all these flavours of A must be stored in the same list).
And, lateron if I retrieve the objects from the list I may have to
know what flavour the object was in order to call the proper
routines for processing them. My question: what does the list look like
in C++? I'm lost, so if
anyone has some advice....

Thanks,

Jeroen

You need to store all different types in the same list? And later you
need to recover what was the type of object stored in the list?

Sorry but in C++ that can't be done.
Oh, come on, John. There is not enough information to conclude that
it "can't be done" in C++.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Mar 6 '07 #4

P: n/a
>>
>>You need to store all different types in the same list? And later you
need to recover what was the type of object stored in the list?

Sorry but in C++ that can't be done.


Oh, come on, John. There is not enough information to conclude that
it "can't be done" in C++.

V
The OP has been asking previously about a library he is writing. I
believe this is about the same code. In other words he has no control
over the types being used, the user of the library could put literally
any type on this list.

This problem cannot be solved as it is stated. Of course if the OP was
prepared to scale back his requirements he might be able to get some
workable code. I think the OP should explain exactly what he is trying
to do.

john
Mar 6 '07 #5

P: n/a
Jeroen wrote:
Hi all,

I have a question which is illustrated by the following piece of code:

template <class T>
class A {
T my_value;
};

In a list, I'd like to store pointers to objects of class A. But I don't
know at forehand if these will be A<intor A<doubleor whatever (all
these flavours of A must be stored in the same list). And, lateron if I
retrieve the objects from the list I may have to know what flavour the
object was in order to call the proper routines for processing them.
[snip]

First, A<intand A<doubleare _unrelated_ types. Thus, A<int>* and
A<double>* are not mutually convertible into one another. That effectively
prevents putting declaring a std::list<what_goes_herethat would contain
A<int>* and A<double>* objects at the same time.

One way to deal with this is:

class A_base {};

template < typename T >
class A : public A_base {
...
};

Now, you could have a std::list<A_base*>. In order to test the dynamic type
at run-time, you could use something like this:

template < typename T >
bool has_A_type ( A_base * ptr ) {
return ( dynamic_cast< A<T>* >( ptr ) != 0 );
}

I am writing this from memory without looking at the standard. So there
might be a problem. However, I am pretty certain that dynamic_cast can be
used some way or another to test for the dynamic type.

Now,

if ( has_A_type<int>( ptr ) ) {
// process int
}
if ( has_A_type<double>( ptr ) ) {
// process int
}
...

will be possible. _However_, it will not be good design.
You should consider putting virtual functions into A_base with overrides in
A<T>. Those will resolve automatically to the correct version for the type.
Ideally that should remove the necessity of testing for the dynamic type.

Best

Kai-Uwe Bux

Mar 6 '07 #6

P: n/a
John Harrison wrote:
>>>
You need to store all different types in the same list? And later you
need to recover what was the type of object stored in the list?

Sorry but in C++ that can't be done.

Oh, come on, John. There is not enough information to conclude that
it "can't be done" in C++.

V


The OP has been asking previously about a library he is writing. I
believe this is about the same code. In other words he has no control
over the types being used, the user of the library could put literally
any type on this list.

This problem cannot be solved as it is stated. Of course if the OP was
prepared to scale back his requirements he might be able to get some
workable code. I think the OP should explain exactly what he is trying
to do.

john
You are right John, this is all in the context of my previous questions.
I'm still in the phase of putting together my requirements, and thinking
of the implications for the code. While doing so I read FAQs and books
to get more knowledge, but my programming skills are rather rusty.
Fortunatly I can take my time because this is not work related :-)

Some more explanation: it was about my matrix class with some extra
facilities. Let's say you can initialize such a matrix like (OK, a
vector in this case to keep it simple...):

{
matrix m = "1 2 3 7 8";
}

But I also want to to use variables in my string expression:

{
matrix m = "1 2 3 7 8";
matrix n;

register_user_var(n);
n = "m 3 4 5 8"; // concatenate vectors 'm' and [3 4 5 8]
}

Explanation:

* register_user_var() should put variable m (in this case of type
'matrix', but it could be a double or bool, or matrix<longas I intend
to write a template for matrix) in the list a referred to in my original
question
* when the string "m 3 4 5 8" is interpreted, the identifier 'm' is
found and looked up in the list.

So I should put in the list for each variable (this is the solution as
far as I came up with):

- pointer to the variable
- string which represents the identifier of the string
- a field that shows what type the variable is.

I thought of a macro that expands:

register_user_var(n)

to:

register_user_variable(static_cast<void *&n, #n, typeid(n).name())

so that the underlying function automatically gets all required
parameters... All fields are stored in a structure that goed into the
list, and can be retrieved if a string is interpreted.

Maybe one of you could think of a better solution to do this. A good
pointer would do, from there I can start looking it up on the internet
or in one of my books :-)

Thanks for your time anyway,

Jeroen
Mar 6 '07 #7

P: n/a
Kai-Uwe Bux wrote:
>Jeroen wrote:
>>Hi all,

I have a question which is illustrated by the following piece of code:

template <class T>
class A {
T my_value;
};

In a list, I'd like to store pointers to objects of class A. But I don't
know at forehand if these will be A<intor A<doubleor whatever (all
these flavours of A must be stored in the same list). And, lateron if I
retrieve the objects from the list I may have to know what flavour the
object was in order to call the proper routines for processing them.

[snip]

First, A<intand A<doubleare _unrelated_ types. Thus, A<int>* and
A<double>* are not mutually convertible into one another. That effectively
prevents putting declaring a std::list<what_goes_herethat would contain
A<int>* and A<double>* objects at the same time.

One way to deal with this is:

class A_base {};

template < typename T >
class A : public A_base {
...
};

Now, you could have a std::list<A_base*>. In order to test the dynamic type
at run-time, you could use something like this:

template < typename T >
bool has_A_type ( A_base * ptr ) {
return ( dynamic_cast< A<T>* >( ptr ) != 0 );
}

I am writing this from memory without looking at the standard. So there
might be a problem. However, I am pretty certain that dynamic_cast can be
used some way or another to test for the dynamic type.

Now,

if ( has_A_type<int>( ptr ) ) {
// process int
}
if ( has_A_type<double>( ptr ) ) {
// process int
}
...

will be possible. _However_, it will not be good design.
You should consider putting virtual functions into A_base with overrides in
A<T>. Those will resolve automatically to the correct version for the type.
Ideally that should remove the necessity of testing for the dynamic type.

Best

Kai-Uwe Bux


OK, I'll take some time to look at this and see if I can synchronize
this with what I want :-) Thanks for thinking with me,

Jeroen
Mar 6 '07 #8

P: n/a
Jeroen wrote:
[..]
Some more explanation: it was about my matrix class with some extra
facilities. Let's say you can initialize such a matrix like (OK, a
vector in this case to keep it simple...):

{
matrix m = "1 2 3 7 8";
Note, that "m" here is only known to the compiler. There is no "m"
during run-time. Just so we're clear...
}

But I also want to to use variables in my string expression:

{
matrix m = "1 2 3 7 8";
matrix n;

register_user_var(n);
n = "m 3 4 5 8"; // concatenate vectors 'm' and [3 4 5 8]
Now, here the first symbol in the string literal is just a value of
the 'char' object. The compiler has no way to associate it with the
object you named 'm' in your program. The interpretation of the string
literal is delayed until the run-time, and then the object's name 'm'
doesn't exist any more (unless you provide some mechanism to keep the
name around, that is).
}

Explanation:

* register_user_var() should put variable m (in this case of type
'matrix', but it could be a double or bool, or matrix<longas I
intend to write a template for matrix) in the list a referred to in
my original question
Uh... So, what I suppose we should be seeing here is

register_user_var(m, "m");

probably, right?
* when the string "m 3 4 5 8" is interpreted, the identifier 'm' is
found and looked up in the list.
OK.. So, you're writing an expression interpreter, eh? Why didn't
you say so before?
So I should put in the list for each variable (this is the solution as
far as I came up with):

- pointer to the variable
- string which represents the identifier of the string
- a field that shows what type the variable is.

I thought of a macro that expands:

register_user_var(n)

to:

register_user_variable(static_cast<void *&n, #n, typeid(n).name())
Aha...

Don't use 'typeid(n).name()', it's utterly unreliable. If you need to
store the type, store 'std::typeinfo' itself ('typeid(n)'), not 'name()'.

But then the biggest question here is what do you do with the 'name'
(or 'typeinfo') afterwards. What kind of cast to you propose to use
to regain access to the object (via a pointer to it) and the object's
inner things? It's very easy to do (void*)&n, but then you have this
'p' of type 'void*', and the name, and 'typeinfo', then what? I can
see how the name is used to look 'p' up. And what do you do with it?
so that the underlying function automatically gets all required
parameters... All fields are stored in a structure that goed into the
list, and can be retrieved if a string is interpreted.
Right. Retrieved. And then what?
Maybe one of you could think of a better solution to do this. A good
pointer would do, from there I can start looking it up on the internet
or in one of my books :-)
The Chapter 6 in Stroustrup's TC++PL describes an expression interpreter.
Check it out.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Mar 6 '07 #9

P: n/a
Jeroen wrote:
John Harrison wrote:
>>>>
You need to store all different types in the same list? And later you
need to recover what was the type of object stored in the list?

Sorry but in C++ that can't be done.


Oh, come on, John. There is not enough information to conclude that
it "can't be done" in C++.

V

The OP has been asking previously about a library he is writing. I
believe this is about the same code. In other words he has no control
over the types being used, the user of the library could put literally
any type on this list.

This problem cannot be solved as it is stated. Of course if the OP was
prepared to scale back his requirements he might be able to get some
workable code. I think the OP should explain exactly what he is trying
to do.

john


You are right John, this is all in the context of my previous questions.
I'm still in the phase of putting together my requirements, and thinking
of the implications for the code. While doing so I read FAQs and books
to get more knowledge, but my programming skills are rather rusty.
Fortunatly I can take my time because this is not work related :-)

Some more explanation: it was about my matrix class with some extra
facilities. Let's say you can initialize such a matrix like (OK, a
vector in this case to keep it simple...):

{
matrix m = "1 2 3 7 8";
}

But I also want to to use variables in my string expression:

{
matrix m = "1 2 3 7 8";
matrix n;

register_user_var(n);
n = "m 3 4 5 8"; // concatenate vectors 'm' and [3 4 5 8]
}

Explanation:

* register_user_var() should put variable m (in this case of type
'matrix', but it could be a double or bool, or matrix<longas I intend
to write a template for matrix) in the list a referred to in my original
question
* when the string "m 3 4 5 8" is interpreted, the identifier 'm' is
found and looked up in the list.

So I should put in the list for each variable (this is the solution as
far as I came up with):

- pointer to the variable
- string which represents the identifier of the string
- a field that shows what type the variable is.

I thought of a macro that expands:

register_user_var(n)

to:

register_user_variable(static_cast<void *&n, #n, typeid(n).name())

so that the underlying function automatically gets all required
parameters... All fields are stored in a structure that goed into the
list, and can be retrieved if a string is interpreted.

Maybe one of you could think of a better solution to do this. A good
pointer would do, from there I can start looking it up on the internet
or in one of my books :-)

Thanks for your time anyway,

Jeroen
The thing that strikes me is, what is the code going to look like that
interprets the list. Given the above I can't see anything except
something like this (apologies for any mistakes)

struct X
{
void* addr;
const char* name;
const char* type;
};

list<Xmy_list;

// get var at front of list
void* addr = my_list.front().addr;
const char* name = my_list.front().name;
const char* type = my_list.front().type;
// do something with var
if (strcmp(type, typeid(int).name()) == 0)
{
int val = *(int*)addr;
// do something with int
}
else if (strcmp(type, typeid(double).name()) == 0)
{
double val = *(double*)addr;
// do something with double
}
etc. etc.

In other words you are limitted in the types you can put on the list by
the code you are going to write to interpret the items on the list.

If this is the case you would be much better off with something similar
to what Kai-Uwe is proposing in his last paragraph. Write a base class
that specifies the inteface that all types must implement (that
interface would specify how the type is to be interpretted when is
appears in one of your initialisation strings). Then any type that
implements the interface would be able to go on the list. This removes
the need for explicit type checking, as Kai-Uwe says.

I think the mistake you have been making upto now is thing that
templates form part of your solution, but this seems much more like a
case for traditional run-time polymorphism, i.e. base classes and
virtual functions.

john
Mar 6 '07 #10

P: n/a
John Harrison wrote:
You need to store all different types in the same list? And later you
need to recover what was the type of object stored in the list?

Sorry but in C++ that can't be done.
Tell that to the author of boost::any.
Mar 6 '07 #11

P: n/a
Noah Roberts wrote:
John Harrison wrote:
>You need to store all different types in the same list? And later you
need to recover what was the type of object stored in the list?

Sorry but in C++ that can't be done.


Tell that to the author of boost::any.
Boost::any does not allow you to 'recover what was the type of object
stored'. Sure you can say, was it an int? was it a double? etc. But in
the absense of any clue (like a fixed list of possibilities) you cannot
tell what the type was.

john
Mar 6 '07 #12

P: n/a
On 3月7日, 上午2时43分, Jeroen <no_m...@please.com>wrote:
Hi all,

I have a question which is illustrated by the following piece of code:

template <class T>
class A {
T my_value;

};

In a list, I'd like to store pointers to objects of class A. But I don't
know at forehand if these will be A<intor A<doubleor whatever (all
these flavours of A must be stored in the same list). And, lateron if I
retrieve the objects from the list I may have to know what flavour the
object was in order to call the proper routines for processing them.

My question: what does the list look like in C++? I'm lost, so if anyone
has some advice....

Thanks,

Jeroen
I suggest use the boost::variant.
On other way , you can do like this:
Plan A..
struct Type_Base
{
virtual std::string type_name() = 0;
virtual void * adress() = 0;
};

template <typename T>
class MyType : Type_Base
{
public:
std::string type_name() { return type_id(T).name(); }
void * address(){ return (void *)(&value);}
private:
T value;
}

Anyway boost::variant is better then paln A,but it only support
arithmetic type. You can read the document for detail.

Mar 7 '07 #13

P: n/a
Jeroen schreef:
John Harrison wrote:
OK guys, you all gave me a lot of pointers to think about. It will keep
me busy for some time to sort everything out. Thanks again!
Mar 7 '07 #14

P: n/a

Jeroen wrote:
>
I have a question which is illustrated by the following piece of code:

template <class T>
class A {
T my_value;
};

In a list, I'd like to store pointers to objects of class A. But I don't
know at forehand if these will be A<intor A<doubleor whatever (all
these flavours of A must be stored in the same list). And, lateron if I
retrieve the objects from the list I may have to know what flavour the
object was in order to call the proper routines for processing them.

My question: what does the list look like in C++? I'm lost, so if anyone
has some advice....
Design pattern "adapter" can be used to adapt templated class into virtual
base interface.

class Base
{
public:
virtual void method()=0;
virtual ~Base(){}
};

template<class T>
class A_Base: public Base
{
A<T data;

public:
void method(){ data.method(); }
};

Multiple ingeritance also can be used

template<class T>
class A_Base: public Base, public A<T>
{
public:
void method(){ A<T>::method(); }
};

--
Maksim A. Polyanin
http://grizlyk1.narod.ru/cpp_new

"In thi world of fairy tales rolls are liked olso"
/Gnume/
Mar 9 '07 #15

P: n/a
On Mar 7, 3:43 am, Jeroen <no_m...@please.comwrote:
Hi all,

I have a question which is illustrated by the following piece of code:

template <class T>
class A {
T my_value;

};

In a list, I'd like to store pointers to objects of class A. But I don't
know at forehand if these will be A<intor A<doubleor whatever (all
these flavours of A must be stored in the same list). And, lateron if I
retrieve the objects from the list I may have to know what flavour the
object was in order to call the proper routines for processing them.

My question: what does the list look like in C++? I'm lost, so if anyone
has some advice....

Thanks,

Jeroen
As a basic technique, you just overload the functions with different
possible types.Compiler will do call the appropriate one.
You can also use typeid operator to identify the type. but it will
make some overhead to your program as it enables Runtime Type
Identification. (RTTI). typeid operator returns a type_info class
which can be use for comparison, type string etc.
You can also approach boost type traits library

Mar 9 '07 #16

P: n/a
On Mar 6, 8:43 pm, Jeroen <no_m...@please.comwrote:
Some more explanation: it was about my matrix class with some extra
facilities. Let's say you can initialize such a matrix like (OK, a
vector in this case to keep it simple...):

{
matrix m = "1 2 3 7 8";
}

But I also want to to use variables in my string expression:

{
matrix m = "1 2 3 7 8";
matrix n;

register_user_var(n);
n = "m 3 4 5 8"; // concatenate vectors 'm' and [3 4 5 8]

}
Hopefully I am not wildly off base here, but it looks like you're
getting yourself in a lot of trouble trying to initialise a matrix via
a string.
Better is something like this:
Matrix<intim(3,3); // 3x3 matrix of ints
im = 1,2,3,
4,5,6,
0,9,8;

This can be achieved by having Matrix<T>::operator=(T) return an
initialiser object - call it Minit<T>.
Then you define Minit<T>::operator,(T) to put T into the Matrix at
the next "slot", and return itself.
I have working code if you want me to post it, this technique is
nabbed from "Generative Programming" by Eisenecker and Czarnecki.

Mar 9 '07 #17

This discussion thread is closed

Replies have been disabled for this discussion.