template member functions of a templated class

J

Jon Wilson

I have a class which needs to accumulate data. The way we get this data
is by calling a member function which returns float on a number of
different objects of different type (they are all the same type for a
given instance of the class, but different types for different instances.)

#include<set>

using namespace std;

template<class T>
class Data
{
private:
set<float> m_data;
mem_fun_ref_t<float, T> m_ftn;
public:
Data() :m_data() {}
}

This is good. Now, I want a function which takes a range of iterators
(which dereference to type T, or in some cases to type T*), and adds all
the data from the iterator range to m_data. It seems like I should be
able to do this with one, or at most two, templated member functions.
How do I deal with having templated member functions inside the
templated class?

template<class T>
class Data
{
---snip
public:
template<class Container>
Add_Data(typename Container<T>::iterator begin,
typename Container<T>::iterator end);
};

gives me the error: Non-template type Container used as a template.

So I try

--snip
public:
template<class C<T> >
Add_Data(typename C<T>::iterator begin,
.... end);
--snip

Which gets the error: C is not a template.

I looked up the STL vector constructor which takes a range of iterators,
and it simply uses a construction like:

--snip
public:
template<class _InputIter>
Add_Data(typename _InputIter begin,
... end);
--snip

However, it seems like then, you could get types which were not in fact
iterators, and even if they were iterators, would dereference to a type
other than T.

Is there a way to restrict what types are acceptable for the template so
that I only get iterators which dereference to T (or T*)?

Also, given that some of the containers I will be taking data from store
T's and some store T*'s, do I need two template functions for these two
possibilities? or just one? or some type of template specialization?
 
V

Victor Bazarov

Jon said:
I have a class which needs to accumulate data. The way we get this data
is by calling a member function which returns float on a number of
different objects of different type (they are all the same type for a
given instance of the class, but different types for different instances.)

#include<set>

using namespace std;

template<class T>
class Data
{
private:
set<float> m_data;
mem_fun_ref_t<float, T> m_ftn;
public:
Data() :m_data() {}
}

This is good. Now, I want a function which takes a range of iterators
(which dereference to type T, or in some cases to type T*), and adds all
the data from the iterator range to m_data. It seems like I should be
able to do this with one, or at most two, templated member functions.
How do I deal with having templated member functions inside the
templated class?

template<class T>
class Data
{
---snip
public:
template<class Container>
Add_Data(typename Container<T>::iterator begin,
typename Container<T>::iterator end);
};

gives me the error: Non-template type Container used as a template.

So I try

--snip
public:
template<class C<T> >

template said:
Add_Data(typename C<T>::iterator begin,

I think you're missing the return value type here...
.... end);
--snip

Which gets the error: C is not a template.

I looked up the STL vector constructor which takes a range of iterators,
and it simply uses a construction like:

--snip
public:
template<class _InputIter>
Add_Data(typename _InputIter begin,

Again, missing the return value type.
... end);
--snip

This way it's actually much better. You will be able to use any type
that complies with the InputIterator requirements.
However, it seems like then, you could get types which were not in fact
iterators, and even if they were iterators, would dereference to a type
other than T.

Of course. But that's the point of templates. Anything that fits should
be able to be used. The requirement is only that _InputIter (BTW, drop
the underscore or lower the case of the first 'i', you're not allowed to
begin a name with "_I", that's reserved) should _only_ satisfy the
following:

operator*() of it should return T

and

operator ++()

should do something that eventually allows you to compare 'begin' and
'end'. See a good book on a better explanation of what InputIterator
should look (or act) like.
Is there a way to restrict what types are acceptable for the template so
that I only get iterators which dereference to T (or T*)?

Yes. By programming the use of specific operators you already restrict
the set of types to those for which those operators are implemented.

Yes, there are other ways to restrict the set of types even further. My
question would be, WHY?
Also, given that some of the containers I will be taking data from store
T's and some store T*'s, do I need two template functions for these two
possibilities? or just one? or some type of template specialization?

You cannot partially specialise a function template, but you can overload
it easily.

Get yourself a decent book on templates and try to begin thinking like its
author (or authors).

V
 
J

Jon Wilson

Yes, there are other ways to restrict the set of types even further. My
question would be, WHY?

Possibly for the purpose of overloading? I'm not sure, see below. And
just out of curiousity, what are those ways? Or do I just have to get a
book on templates so I can start thinking like the authors?
You cannot partially specialise a function template, but you can overload
it easily.

In this case, how would I go about overloading it, since the function
signatures would be the same? I thought that you had to have at least
one type (either parameter or return) which was different, and since I'm
using templates, there would be the same number of parameters, and they
would both be of generic type, and the return type (sorry I forgot
those, they should have all been void) is the same. So how can
overloading be done here without adding an extra parameter as a dummy
for the sole purpose of distinguishing the two functions (which seems
rather kludgey to me)?
Get yourself a decent book on templates and try to begin thinking like its
author (or authors).

V

I would very much like to get a good book on templates... do you have
any recommendations? How about donating the 50+ bucks it'll cost me?...
I'm a PCK (poor college kid) and newsgroups are free.

Since I do not _have_ such a book at this time, and I _do_ have an
immediate problem with templates in my program, I thought I'd ask here,
where there are people who have the money to afford such books. Perhaps
I can begin to think like the people on this and other newsgroups, who
presumably think like the author (or authors) of the books. But I see
that such questions are met with derision... Sorry to have disturbed you.
 
V

Victor Bazarov

Jon said:
Possibly for the purpose of overloading?

I have no idea what that means.
I'm not sure, see below. And
just out of curiousity, what are those ways?

The usual way is to produce some kind of "compile-time assert failure"
using templates. Search for "type lists" or "is_convertible" or ...
Who knows, you might even invent your own way.
Or do I just have to get a
book on templates so I can start thinking like the authors?

It never hurts to get (and hopefully read) good books.
In this case, how would I go about overloading it, since the function
signatures would be the same?

How are they the same? One is based on objects, the other on pointers.
I thought that you had to have at least
one type (either parameter or return) which was different, and since I'm
using templates, there would be the same number of parameters, and they
would both be of generic type, and the return type (sorry I forgot
those, they should have all been void) is the same. So how can
overloading be done here without adding an extra parameter as a dummy
for the sole purpose of distinguishing the two functions (which seems
rather kludgey to me)?

AFAIUI
template<class T> void foo(T);
and
template<class T> void foo(T*);

are overloaded. Now you need to figure out what argument you want to
pass. And you can always specify template arguments directly:

foo<int>(blah
or
foo said:
I would very much like to get a good book on templates... do you have
any recommendations?

"C++ Templates" by Vandevoorde and Josuttis. "Modern C++ Design" by
Alexandrescu.
How about donating the 50+ bucks it'll cost me?...

As soon as I win the lottery.
I'm a PCK (poor college kid) and newsgroups are free.

Libraries are free as well (well, most of them anyway).
Since I do not _have_ such a book at this time, and I _do_ have an
immediate problem with templates in my program, I thought I'd ask here,
where there are people who have the money to afford such books. Perhaps
I can begin to think like the people on this and other newsgroups, who
presumably think like the author (or authors) of the books. But I see
that such questions are met with derision...

Wow... Did they now teach to respond like that in college?
Sorry to have disturbed you.

Aw, quit your whining. Have you even considered looking in the news
archives before asking again?
 
J

Jeff Flinn

Jon Wilson wrote:


Since I do not _have_ such a book at this time, and I _do_ have an
immediate problem with templates in my program, I thought I'd ask
here, where there are people who have the money to afford such books.

With a Fermilab address, I'd think you'd find a copy laying around or in the
office library.

You can also go to a Border's or Barnes & Noble, buy a cup of coffee and sit
in the cafe with the book.
Perhaps I can begin to think like the people on this and other
newsgroups, who presumably think like the author (or authors) of the
books. But I see that such questions are met with derision... Sorry
to have disturbed you.

Have you heard the one about looking a gift horse in the mouth?

Jeff
 
J

Jon Wilson

Victor said:
I have no idea what that means.

It means that since I was not sure what those methods of restricting
types further are, I could not ignore the possibility that they might
change the function signature, in which case, two different functions
which restrict the types in different ways would have different
signatures, and could be overloaded versions of the same function.
The usual way is to produce some kind of "compile-time assert failure"
using templates. Search for "type lists" or "is_convertible" or ...
Who knows, you might even invent your own way.

Thank you. Given this answer I do not think that these restrictions on
template types change the function signature at all, and thus would have
no effect on overloading.
How are they the same? One is based on objects, the other on pointers.

AFAIUI
template<class T> void foo(T);
and
template<class T> void foo(T*);

are overloaded. Now you need to figure out what argument you want to
pass. And you can always specify template arguments directly:

foo<int>(blah
or
foo<int*>(blah

If I use the form

template<class T>
class Data
{
--snip
public:
template<class inputIter>
void Add_Data(typename inputIter, typename inputIter);
};

in which both arguments are generic types, then the function signatures
for a function in which the inputIter dereferences to objects and for a
function in which the inputIter dereferences to pointers are identical.
AFAIK. Is there some reason that this would not be the case? Note,
that I am not using:

template<class T> foo(T t);
and
template<class T> foo(T* p);

which obviously would be overloaded, since the function signatures are
different.

So, I ask again: In this case, how can overloading be done, since the
function signatures are the same? Or am I overlooking some reason why
they might be different?

I would ask your forgiveness for my somewhat irritable previous
response... I was frustrated that I couldn't figure out this problem,
and I perceived your injunction to think like the authors to be a
statement that I was a poor programmer. Which I may well be (although I
like to think not), but nobody likes to be insulted, and given my
already high level of frustration, I kinda lashed out. My apologies.

Regards,
Jon
 
V

Victor Bazarov

Jon said:
If I use the form

template<class T>
class Data
{
--snip
public:
template<class inputIter>
void Add_Data(typename inputIter, typename inputIter);
};

in which both arguments are generic types, then the function signatures
for a function in which the inputIter dereferences to objects and for a
function in which the inputIter dereferences to pointers are identical.
AFAIK. Is there some reason that this would not be the case? Note,
that I am not using:

template<class T> foo(T t);
and
template<class T> foo(T* p);

which obviously would be overloaded, since the function signatures are
different.

So, I ask again: In this case, how can overloading be done, since the
function signatures are the same? Or am I overlooking some reason why
they might be different?

Well, without knowing what problem you're trying to solve, it's rather
impossible to give a more precise recommendation, but why couldn't you
do something like

template<class T>
class Data
{
--snip
public:
void Add_One_Element(T t);
void Add_One_Element(T* t);
template<class I> void Add_Data(I i1, I i2) {
while (i1 != i2)
Add_One_Element(*i1++);
}
};

Notice, I didn't overload the 'Add_Data' thing, just introduced another
overloaded member function that will be called by template instantiations
of 'Add_Data' depending on the return type of I::eek:perator*().

V
 
J

Jon Wilson

Victor said:
Well, without knowing what problem you're trying to solve, it's rather
impossible to give a more precise recommendation, but why couldn't you
do something like

template<class T>
class Data
{
--snip
public:
void Add_One_Element(T t);
void Add_One_Element(T* t);
template<class I> void Add_Data(I i1, I i2) {
while (i1 != i2)
Add_One_Element(*i1++);
}
};

Notice, I didn't overload the 'Add_Data' thing, just introduced another
overloaded member function that will be called by template instantiations
of 'Add_Data' depending on the return type of I::eek:perator*().

V

Ahhh... yes, I think that just might work. Thank you for your help!

BTW, just for my future reference, was the description I gave of the
problem I was trying to solve in my original post insufficient? If so,
how can I improve upon it in order to do a better job for future posts?
Of course, this is not a critical issue, so if you're too busy or
anything, don't bother responding. I'm just curious.
 
V

Victor Bazarov

Jon said:
[...]
BTW, just for my future reference, was the description I gave of the
problem I was trying to solve in my original post insufficient? If so,
how can I improve upon it in order to do a better job for future posts?
Of course, this is not a critical issue, so if you're too busy or
anything, don't bother responding. I'm just curious.

The original description was fine. But description is not everything.

I remember the old fable: a young man and a girl are in a subway station
necking, paying no attention to the world. An old dude walks by, stops,
and addressing the couple, says, "you are young folk, you think the life
is simple... But the life is so much simpler".

Perhaps I sometimes tend to overemphasize this, but it's often helpful
to just let go of the complicated stuff and become minimalist. Use only
enough effort to get by, you will find that in many situations when C++
is concerned, less is more (regardless of how much I hate that saying).

Templates ("compile-time polymorphism") are (just like the run-time
polymorphism) good when they are not over-complicated by the rest of the
code. You can always make your code very complex and cover all bases and
outfield along with them. Question is, what do you really solve with too
much specifics?...

Ah, don't listen, I'm just rambling like that old dude.

V
 
J

Jon Wilson

Thanks, Victor, you've been very helpful, and I really appreciate it!

Regards,
Jon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,815
Latest member
treekmostly22

Latest Threads

Top