Re: template member functions of a templated class

From: Victor Bazarov (v.Abazarov_at_comAcast.net)
Date: 01/07/05


Date: Fri, 07 Jan 2005 15:10:21 -0500

Jon Wilson wrote:
> 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<template C<class> > ...

> 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



Relevant Pages