Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   template partial specialization (http://www.velocityreviews.com/forums/t267649-template-partial-specialization.html)

Chandra Shekhar Kumar 06-24-2003 12:35 AM

Re: template partial specialization
 


Paul MG wrote:

> Hi
>
> Template partial specialization always seems like a fairly
> straightforward concept - until I try to do it :).
>
> I am trying to implement the input sequence type (from Stroustrup
> section 18.3.1, 'Iseq'). I want the version for containers that he
> gives, but also to provide a specialization for construction from a
> pair<It,It> (eg because that is returned by equal_range()). [Iseq is
> actually implemented as a pair<> - but that is a separate issue.]
>
> Here is what I have:
>
> // ---------------------------------------------------------------
>
> // A type representing an 'input sequence':
>
> template<class In>
> class Iseq : public pair<In, In> {
> public:
> Iseq(In i1, In i2) : pair<In, In>(i1, i2) {}
> bool IsEmpty() const { return first == second; }
> };
>
> // A helper function to make one (since ctors can't
> // infer the types of template arguments):
>
> template<class C>
> Iseq<typename C::iterator> iseq(C& c) {
> return Iseq<typename C::iterator>(c.begin(), c.end());
> }
>
> // A specialisation for pairs:
>
> template<class T>
> Iseq<T> iseq_p(pair<T, T> p) {
> return Iseq<T>(p.first, p.second);
> }


this is not specialisation of class Iseq for pairs if u replace iseq_p
with Iseq. it is a function.
the specialisation is:

template <>
template <class T>
class Iseq<pair<T,T> >
{
public:
Iseq(pair<T,T> pairv): pair<T,T>(pairv.first, pairv.second)
};

this is not the solution to yr problem though, but it will give u the
basic idea.

>
>
> // An overloaded version of STL find() taking an input sequence:
>
> template<class In, class T>
> In find(Iseq<In> r, const T& v) { return find(r.first, r.second, v);
> }
>
> // And finally, a client:
>
> Iseq<MMIt> FindMemberships(UserReference member) {
> return iseq_p( memberships_.equal_range(member) );
> }
> MMIt MemberAt(UserReference member, Path path) {
> return find(FindMemberships(member), make_pair(member,
> path));
> }
>
> // ---------------------------------------------------------------
>
>
> This works. But only because I have renamed my 'specialisation' of
> iseq() for pairs to iseq_p. I don't want to (and don't think I have
> to) do that, for this or any further specialisations. Simply replacing
> 'iseq_p' with 'iseq' in the above causes the compiler (gcc2.95) to
> attempt to use the first definition of iseq, and it (rightly)
> complains that pair<>::iterator does not exist. What mistake am I
> making?
>
> [ As an aside: Stroustrup makes Iseq<T> publicly inherit pair<T,T>. I
> might be inclined to make it privately inherit it - surely no client
> wants to use the pair<> interface? ]



Chandra Shekhar Kumar 06-24-2003 12:36 AM

Re: template partial specialization
 


Paul MG wrote:

> Hi
>
> Template partial specialization always seems like a fairly
> straightforward concept - until I try to do it :).
>
> I am trying to implement the input sequence type (from Stroustrup
> section 18.3.1, 'Iseq'). I want the version for containers that he
> gives, but also to provide a specialization for construction from a
> pair<It,It> (eg because that is returned by equal_range()). [Iseq is
> actually implemented as a pair<> - but that is a separate issue.]
>
> Here is what I have:
>
> // ---------------------------------------------------------------
>
> // A type representing an 'input sequence':
>
> template<class In>
> class Iseq : public pair<In, In> {
> public:
> Iseq(In i1, In i2) : pair<In, In>(i1, i2) {}
> bool IsEmpty() const { return first == second; }
> };
>
> // A helper function to make one (since ctors can't
> // infer the types of template arguments):
>
> template<class C>
> Iseq<typename C::iterator> iseq(C& c) {
> return Iseq<typename C::iterator>(c.begin(), c.end());
> }
>
> // A specialisation for pairs:
>
> template<class T>
> Iseq<T> iseq_p(pair<T, T> p) {
> return Iseq<T>(p.first, p.second);
> }


this is not specialisation of class Iseq for pairs if u replace iseq_p
with Iseq. it is a function.
the specialisation is:

template <>
template <class T>
class Iseq<pair<T,T> >
{
public:
Iseq(pair<T,T> pairv): pair<T,T>(pairv.first, pairv.second)
};

this is not the solution to yr problem though, but it will give u the
basic idea.

>
>
> // An overloaded version of STL find() taking an input sequence:
>
> template<class In, class T>
> In find(Iseq<In> r, const T& v) { return find(r.first, r.second, v);
> }
>
> // And finally, a client:
>
> Iseq<MMIt> FindMemberships(UserReference member) {
> return iseq_p( memberships_.equal_range(member) );
> }
> MMIt MemberAt(UserReference member, Path path) {
> return find(FindMemberships(member), make_pair(member,
> path));
> }
>
> // ---------------------------------------------------------------
>
>
> This works. But only because I have renamed my 'specialisation' of
> iseq() for pairs to iseq_p. I don't want to (and don't think I have
> to) do that, for this or any further specialisations. Simply replacing
> 'iseq_p' with 'iseq' in the above causes the compiler (gcc2.95) to
> attempt to use the first definition of iseq, and it (rightly)
> complains that pair<>::iterator does not exist. What mistake am I
> making?
>
> [ As an aside: Stroustrup makes Iseq<T> publicly inherit pair<T,T>. I
> might be inclined to make it privately inherit it - surely no client
> wants to use the pair<> interface? ]



Paul MG 06-24-2003 11:39 AM

template partial specialization
 
Hi

Template partial specialization always seems like a fairly
straightforward concept - until I try to do it :).

I am trying to implement the input sequence type (from Stroustrup
section 18.3.1, 'Iseq'). I want the version for containers that he
gives, but also to provide a specialization for construction from a
pair<It,It> (eg because that is returned by equal_range()). [Iseq is
actually implemented as a pair<> - but that is a separate issue.]

Here is what I have:

// ---------------------------------------------------------------

// A type representing an 'input sequence':

template<class In>
class Iseq : public pair<In, In> {
public:
Iseq(In i1, In i2) : pair<In, In>(i1, i2) {}
bool IsEmpty() const { return first == second; }
};

// A helper function to make one (since ctors can't
// infer the types of template arguments):

template<class C>
Iseq<typename C::iterator> iseq(C& c) {
return Iseq<typename C::iterator>(c.begin(), c.end());
}

// A specialisation for pairs:

template<class T>
Iseq<T> iseq_p(pair<T, T> p) {
return Iseq<T>(p.first, p.second);
}

// An overloaded version of STL find() taking an input sequence:

template<class In, class T>
In find(Iseq<In> r, const T& v) { return find(r.first, r.second, v);
}

// And finally, a client:

Iseq<MMIt> FindMemberships(UserReference member) {
return iseq_p( memberships_.equal_range(member) );
}
MMIt MemberAt(UserReference member, Path path) {
return find(FindMemberships(member), make_pair(member,
path));
}

// ---------------------------------------------------------------


This works. But only because I have renamed my 'specialisation' of
iseq() for pairs to iseq_p. I don't want to (and don't think I have
to) do that, for this or any further specialisations. Simply replacing
'iseq_p' with 'iseq' in the above causes the compiler (gcc2.95) to
attempt to use the first definition of iseq, and it (rightly)
complains that pair<>::iterator does not exist. What mistake am I
making?

[ As an aside: Stroustrup makes Iseq<T> publicly inherit pair<T,T>. I
might be inclined to make it privately inherit it - surely no client
wants to use the pair<> interface? ]

Chandra Shekhar Kumar 06-24-2003 08:41 PM

Re: template partial specialization
 


> Hmmmm... so if you define a templated function
>
> template<class T> iseq(T);
>
> and then later add
>
> template<> iseq(SomeType);
>
> then the second is a function overload not a specialization?


this is template function specialisation.

> That is
> what I am trying to do (I think). Its just that when SomeType is
> 'pair<T1,T2>', you need to specify T1 and T2 too so you can't just say
> 'template<>' like I have here...


yes, u shud write:

template<> template <typename T1, typename T2> iseq(pair<T1, T2>)



Chandra Shekhar Kumar 06-24-2003 08:47 PM

Re: template partial specialization
 

sorry...i messed up a bit....
what i meant is:
template <> is not partial specialization, it is fully specialisation :-))


Chandra Shekhar Kumar 06-25-2003 01:01 AM

Re: template partial specialization
 
>
> >
> > template<> template <typename T1, typename T2> iseq(pair<T1, T2>)

>
> What is the above supposed to be? It isn't legal code, in any case.


see the code below and run it, u will understand what i meant by
above...............(use a good compiler ::-))

#include <iostream>
#include <map>

using namespace std;

template<class T> h(T a) { cout << "h::" << a << endl; }

template<> template<class T1, class T2> h(pair<T1, T2>& p) { cout << "pair::"
<< p.first << ":::" << p.second << endl;}

int main()
{
h(20);
pair<int, float> p(20, 30.34);
h(p);
}




Chandra Shekhar Kumar 06-25-2003 01:04 AM

Re: template partial specialization
 
> That is
> >what I am trying to do (I think). Its just that when SomeType is
> >'pair<T1,T2>', you need to specify T1 and T2 too so you can't just say
> >'template<>' like I have here...

>
> Ahh, so you are trying to partially specialize a function template.
> That isn't possible in C++.


u r wrong....
see the code below::


#include <iostream>
#include <map>

using namespace std;

template<class T> h(T a) { cout << "h::" << a << endl; }

template<> template<class T1, class T2> h(pair<T1, T2>& p) { cout << "pair::"
<< p.first << ":::" << p.second << endl;}

int main()
{
h(20);
pair<int, float> p(20, 30.34);
h(p);
}




Chandra Shekhar Kumar 06-25-2003 01:16 AM

Re: template partial specialization
 
so , now the question is when to choose function templates, and when function
overloading.....
the limitation of function templates is that they donot scale well.
what i mean is: with the function templates having 2 or more arguments cann't
be fully specilaized.

see the code below:

#include <iostream>
#include <map>

using namespace std;

template<class T1, class T2> f(T1 a, T2 b) { cout << a << ":" << b << endl;}

//partial specialization of f......

template<class T1> f(T1 a, int b) { cout << "partial::" << a << ":" << b <<
endl;}


//fully specialisation of f.....not legal code...so commented.....

//template<> f(int a, int b) { cout << "fully:::" << a << ":" << b << endl;}


template <class T> g(T a) { cout << "g:: " << a << endl;}

//fully specialisation of g.....legal here coz g takes only one argument.....

template<> g(int a) { cout << "fully::g:::" << a << endl;}



template<class T> h(T a) { cout << "h::" << a << endl; }

//fully specialisation...same as above....:-)))

template<> template<class T1, class T2> h(pair<T1, T2>& p) { cout << "pair::"
<< p.first << ":::" << p.second << endl;}


int main()
{
f(5.45,4.56);
f(34.45, 3);
f(2, 3);
g(3.45);
g(2);

h(20);
pair<int, float> p(20, 30.34);
h(p);
}



Chandra Shekhar Kumar 06-25-2003 02:46 AM

Re: template partial specialization
 
>
> > #include <iostream>
> > #include <map>
> >
> > using namespace std;
> >
> > template<class T> h(T a) { cout << "h::" << a << endl; }
> >
> > template<> template<class T1, class T2> h(pair<T1, T2>& p) { cout <<

> "pair::"
> > << p.first << ":::" << p.second << endl;}
> >
> > int main()
> > {
> > h(20);
> > pair<int, float> p(20, 30.34);
> > h(p);
> > }

>
> This code doesn't compile. It's plain bogus. Please try to
> compile any code before you post it.


hi Victor, actually i compiled the above with g++ 2.8.1 and it ran well...
but i tried the same with Comeau too and u r right there....
it's not standard code....g++ guys are lenient i think.....
but my main point is this: function templates can be specialised ....see my
next posting of the code(pl forgive me for missing the return types , i meant
it to be void though :-))

i tried it with Comeau too, and it run....
#include <iostream>
#include <map>

using namespace std;

template<class T1, class T2> void f(T1 a, T2 b) { cout << a << ":" << b <<
endl;}

//partial specialization of f......

template<class T1> void f(T1 a, int b) { cout << "partial::" << a << ":" << b
<<
endl;}


//fully specialisation of f.....not legal code...so commented.....

//template<> f(int a, int b) { cout << "fully:::" << a << ":" << b << endl;}


template <class T> void g(T a) { cout << "g:: " << a << endl;}

//fully specialisation of g.....legal here coz g takes only one argument.....

template<> void g(int a) { cout << "fully::g:::" << a << endl;}




int main()
{
f(5.45,4.56);
f(34.45, 3);
f(2, 3);
g(3.45);
g(2);


}


and the book i refer is "Modern C++ Design" by Andrei....

Thanks for yr input , no offense :-)))

Chandra


Paul MG 06-25-2003 08:22 AM

Re: template partial specialization
 
> > // A specialisation for pairs:
> >
> > template<class T>
> > Iseq<T> iseq_p(pair<T, T> p) {
> > return Iseq<T>(p.first, p.second);
> > }

>
> That isn't a specialization, but a function overload.


Hmmmm... so if you define a templated function

template<class T> iseq(T);

and then later add

template<> iseq(SomeType);

then the second is a function overload not a specialization? That is
what I am trying to do (I think). Its just that when SomeType is
'pair<T1,T2>', you need to specify T1 and T2 too so you can't just say
'template<>' like I have here...

> >Simply replacing
> >'iseq_p' with 'iseq' in the above causes the compiler (gcc2.95) to
> >attempt to use the first definition of iseq, and it (rightly)
> >complains that pair<>::iterator does not exist. What mistake am I
> >making?

>
> Using a 3 year old compiler. Upgrade to gcc 3.0+ and it will work
> fine. The missing feature is "partial template function ordering",
> which knows how to choose the best match amongst different template
> specializations that match a function call.


I have other places in the code where it correctly chooses the 'most
specific' implementation of a templated function just like what I
outlined above. So I don't think it is total lack of compiler support
- it could be a failure to support something in this specific case I
suppose, yes.

> >[ As an aside: Stroustrup makes Iseq<T> publicly inherit pair<T,T>. I
> >might be inclined to make it privately inherit it - surely no client
> >wants to use the pair<> interface? ]

>
> Your find overload does...


Only cos I copied it out of Stroustrup. I would have preferred to
inherit Iseq<T> privately from pair<T,T>, and give it accessors
begin() and end() which return pair<T,T>::first and pair<T,T>::second.

But I am unwilling to assume that I am cleverer than Stroustrup :).
Someone let me know my error?

cheers!

pmg


All times are GMT. The time now is 04:14 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.