![]() |
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? ] |
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? ] |
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? ] |
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>) |
Re: template partial specialization
sorry...i messed up a bit.... what i meant is: template <> is not partial specialization, it is fully specialisation :-)) |
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); } |
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); } |
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); } |
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 |
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 01:35 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.