473,721 Members | 2,053 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Template class partial specialisation problem

Greetings.

The following code compiles ok and does what I'd expect it to do:

[apologies for the lack of indentation... Google Groups 2 Beta bug
reported]

---------- START CODE ----------

// test.cpp

#include <iostream>

template <class T> struct A
{
A();
};

A<int>::A()
{
std::cout << "Template parameter is \"int\"" << '\n';
}

A<long>::A()
{
std::cout << "Template parameter is \"long\"" << '\n';
}

int main()
{
A<int> a1;
A<long> a2;

return 0;
}

---------- END CODE ----------

The program outputs:

Template parameter is "int"
Template parameter is "long"

So far so good... now I would like to do the same, but there is a
second template parameter and I only want to specialise on the first:

---------- START CODE ----------

// test.cpp

#include <iostream>

template <class T, class R> struct A
{
A();
};

template <class R> A<int, R>::A() // line 10
{
std::cout << "First template parameter is \"int\"" << '\n';
}

template <class R> A<long, R>::A() // line 15
{
std::cout << "First template parameter is \"long\"" << '\n';
}

int main()
{
A<int, int> a1;
A<long, int> a2;

return 0;
}

---------- END CODE ----------

My compiler (gcc 3.3.3 cygwin special) throws this out with:

g++ test.cpp -o test.exe
test.cpp:10: error: parse error before `)' token
test.cpp:15: error: parse error before `)' token

I can't figure out quite what the syntax should be to specialise on the
first template parameter only. It would seem that A<int, R>::A() is
still a template function, but my compiler doesn't like the "obvious"
definition:
template <class R> A<int, R>::A()

Any help appreciated,

--
Lionel B

Jul 22 '05 #1
7 2128
Lionel B wrote:
Greetings.

The following code compiles ok and does what I'd expect it to do:

[apologies for the lack of indentation... Google Groups 2 Beta bug
reported]

---------- START CODE ----------

// test.cpp

#include <iostream>

template <class T> struct A
{
A();
};

A<int>::A()
{
std::cout << "Template parameter is \"int\"" << '\n';
}

A<long>::A()
{
std::cout << "Template parameter is \"long\"" << '\n';
}

int main()
{
A<int> a1;
A<long> a2;

return 0;
}

---------- END CODE ----------

The program outputs:

Template parameter is "int"
Template parameter is "long"

So far so good... now I would like to do the same, but there is a
second template parameter and I only want to specialise on the first:

---------- START CODE ----------

// test.cpp

#include <iostream>

template <class T, class R> struct A
{
A();
};

template <class R> A<int, R>::A() // line 10
{
std::cout << "First template parameter is \"int\"" << '\n';
}

template <class R> A<long, R>::A() // line 15
{
std::cout << "First template parameter is \"long\"" << '\n';
}

int main()
{
A<int, int> a1;
A<long, int> a2;

return 0;
}

---------- END CODE ----------

My compiler (gcc 3.3.3 cygwin special) throws this out with:

g++ test.cpp -o test.exe
test.cpp:10: error: parse error before `)' token
test.cpp:15: error: parse error before `)' token

I can't figure out quite what the syntax should be to specialise on the
first template parameter only. It would seem that A<int, R>::A() is
still a template function, but my compiler doesn't like the "obvious"
definition:
template <class R> A<int, R>::A()


I believe to partially specialise a member, you need to partially
specialise the class first. You need to add these lines before the
member specialisations :

template<class R> struct A<int,R> { A(); };
template<class R> struct A<long,R> { A(); };

Victor
Jul 22 '05 #2
Victor Bazarov wrote:
Lionel B wrote:


/snip/
I can't figure out quite what the syntax should be to specialise
on the first template parameter only. It would seem that
A<int, R>::A() is still a template function, but my compiler
doesn't like the "obvious" definition:
template <class R> A<int, R>::A()


I believe to partially specialise a member, you need to partially
specialise the class first. You need to add these lines before the
member specialisations :

template<class R> struct A<int,R> { A(); };
template<class R> struct A<long,R> { A(); };


Cheers, Victor. But that leaves me with a problem; it seems then that I
have to partially specialise *every member function* in the class.
e.g.:

---------- START CODE ----------

// test.cpp

#include <iostream>

template <class T, class R> struct A
{
A();
void foo() {}
};

template<class R> struct A<int,R> {A();};
template<class R> A<int, R>::A()
{
std::cout << "First template parameter is \"int\"" << '\n';
}

template<class R> struct A<long,R> {A();};
template<class R> A<long, R>::A()
{
std::cout << "First template parameter is \"long\"" << '\n';
}

int main()
{
A<int, int> a1;
A<long, int> a2;

a1.foo();
a2.foo();

return 0;
}

---------- END CODE ----------

g++ test.cpp -o test.exe
test.cpp: In function `int main()':
test.cpp:28: error: `foo' undeclared (first use this function)
test.cpp:28: error: (Each undeclared identifier is reported only once
for each
function it appears in.)

Problem is my class has *many* member functions, but only a handful of
them need to be partially specialised. Surely I shouldn't have to
re-write identical code for every member function that does not need to
be partially specialised?

--
Lionel B

Now this is really not on for my class, as there is no way I

Jul 22 '05 #3
Lionel B wrote:
Victor Bazarov wrote:
Lionel B wrote:

/snip/

I can't figure out quite what the syntax should be to specialise
on the first template parameter only. It would seem that
A<int, R>::A() is still a template function, but my compiler
doesn't like the "obvious" definition:
template <class R> A<int, R>::A()


I believe to partially specialise a member, you need to partially
specialise the class first. You need to add these lines before the
member specialisations :

template<clas s R> struct A<int,R> { A(); };
template<clas s R> struct A<long,R> { A(); };

Cheers, Victor. But that leaves me with a problem; it seems then that I
have to partially specialise *every member function* in the class.


Why?
e.g.:

---------- START CODE ----------

// test.cpp

#include <iostream>

template <class T, class R> struct A
{
A();
void foo() {}
};

template<class R> struct A<int,R> {A();};
template<class R> A<int, R>::A()
{
std::cout << "First template parameter is \"int\"" << '\n';
}

template<class R> struct A<long,R> {A();};
template<class R> A<long, R>::A()
{
std::cout << "First template parameter is \"long\"" << '\n';
}

int main()
{
A<int, int> a1;
A<long, int> a2;

a1.foo();
a2.foo();

return 0;
}

---------- END CODE ----------

g++ test.cpp -o test.exe
test.cpp: In function `int main()':
test.cpp:28: error: `foo' undeclared (first use this function)
test.cpp:28: error: (Each undeclared identifier is reported only once
for each
function it appears in.)

Problem is my class has *many* member functions, but only a handful of
them need to be partially specialised. Surely I shouldn't have to
re-write identical code for every member function that does not need to
be partially specialised?
By partial specialisation of a template class you create another template.
You're responsible for its contents. If you say that it's not going to
have the 'foo' member, it's not going to have the 'foo' member. But if
you try to use the 'foo' member, you get an error. You're basically
contradicting yourself here. OOH you say, here is a special variation of
my A template, see? It doesn't have a foo function. Then you say, no I
do want it to have a foo function. So, which is it? It's a rhetorical
question...

One thing you should remember, there is no partial specialisation of
function templates. None. Not allowed. That basically means no partial
specialisations of member functions, either, by themselves. What you are
allowed to create is a full specialisation of a member of another class
template, who just happens to be a partial specialisation of your original
class template.

Such is life.

--
Lionel B

Now this is really not on for my class, as there is no way I


Huh? Sorry, I can't say I understand what you're trying to say here.
Jul 22 '05 #4
Victor Bazarov wrote:
Lionel B wrote:
Victor Bazarov wrote:
Lionel B wrote:
/snip/
I can't figure out quite what the syntax should
be to specialise on the first template parameter
only. It would seem that A<int, R>::A() is still
a template function, but my compiler doesn't like
the "obvious" definition:
template <class R> A<int, R>::A()

I believe to partially specialise a member, you need
to partially specialise the class first. You need to
add these lines before the member specialisations :

template<clas s R> struct A<int,R> { A(); };
template<clas s R> struct A<long,R> { A(); };


Cheers, Victor. But that leaves me with a problem; it
seems then that I have to partially specialise *every
member function* in the class.


Why?


Read on.

/snip/
Problem is my class has *many* member functions, but only
a handful of them need to be partially specialised. Surely
I shouldn't have to re-write identical code for every member
function that does not need to be partially specialised?


By partial specialisation of a template class you create another
template. You're responsible for its contents. If you say that
it's not going to have the 'foo' member, it's not going to have
the 'foo' member. But if you try to use the 'foo' member, you
get an error.


What I would really like is that if a member function - foo, say - is
not explicitly (partially) specialised, then the definition of the
un-specialised foo member from the un-specialised template class is
picked up. This works perfectly well with full specialisation:

---------- BEGIN CODE ----------

#include <iostream>

template <class T> struct A
{
A();
void foo()
{
std::cout << "This is foo" << '\n';
}
};

A<int>::A()
{
std::cout << "Template parameter is \"int\"" << '\n';
}

A<long>::A()
{
std::cout << "Template parameter is \"long\"" << '\n';
}

int main()
{
A<int> a1;
A<long> a2;

a1.foo();
a2.foo();

return 0;
}

---------- END CODE ----------

works perfectly well. Output:

Template parameter is "int"
Template parameter is "long"
This is foo
This is foo

Here foo is simply picked up from its definition in the the
un-specialised template class. Now I honestly don't see why this
couldn't be the case for partial specialisation (evidently it isn't).

To my mind this renders partial specialisation less than useful. If I'm
going to have to write different definitions for every function of a
partial specialisation of a template class, I may as well be done with
it and write separate template classes for each specialisation!

/snip/
One thing you should remember, there is no partial specialisation
of function templates. None. Not allowed. That basically means
no partial specialisations of member functions, either, by
themselves.
Yup. That's precisely what I want... I suppose there must be a good
reason for this, but I can't see it. As I say, it seems to work ok for
full specialisation.
What you are
allowed to create is a full specialisation of a member of another
class template, who just happens to be a partial specialisation of
your original class template.


Not sure I follow you here.
Now this is really not on for my class, as there is no way I


Huh? Sorry, I can't say I understand what you're trying to say here.

Me neither. Editing glitch.

--
Lionel B

Jul 22 '05 #5
Lionel B wrote:
[...]
To my mind this renders partial specialisation less than useful. If I'm
going to have to write different definitions for every function of a
partial specialisation of a template class, I may as well be done with
it and write separate template classes for each specialisation!


But that is what you essentially do when you partially specialise a class
template. You _essentially_ create another template. Sort of.
One thing you should remember, there is no partial specialisation
of function templates. None. Not allowed. That basically means
no partial specialisations of member functions, either, by
themselves.

Yup. That's precisely what I want... I suppose there must be a good
reason for this, but I can't see it. As I say, it seems to work ok for
full specialisation.


See "C++ Templates" by Vandevoorde and Josuttis, section 13.7. I am too
lazy to re-type it all here.
What you are
allowed to create is a full specialisation of a member of another
class template, who just happens to be a partial specialisation of
your original class template.

Not sure I follow you here.


I am not sure I follow myself. Never mind. Get the Vandevoorde/Josuttis
book and many things are going to be clearer.

V
Jul 22 '05 #6
"Lionel B" <go****@lionelb .com> wrote in message news:<10******* *************** @f14g2000cwb.go oglegroups.com> ...
Greetings.


<snip>

You may solve your issues by combining templates with inheritance.
You write one (or many) base template class(es) and then subclass from
them with reduced set of template parameters. This will pull all
virtuals form the base which will be automatically specialized, but
which you will still be able to overwrite.

This will not always work, precisely because ALL base class function
will be specialized in this approach (following standard instantiation
rules), which may result in some illegal code being generated. That's
why one may need to finer slice the superclass into several classes.

Also, this will work only when the context will allow you to use the
inherited methods polymorphically . Eg, it will not work in
constructors.

Back to Earth, your example could mutate into something like this:

/******/
#include <iostream>
#include <string>

// need these (or comparable) functions that implement static
polymorphism
// because constructors can only be statically polymorphic
template<typena me _T>
static std::string const&
TypeToString();

template<>
static std::string const&
TypeToString<in t>()
{
static std::string const ret = std::string("in t");
return ret;
}

template<>
static std::string const&
TypeToString<lo ng>()
{
static std::string const ret = std::string("lo ng");
return ret;
}

template<>
static std::string const&
TypeToString<do uble>()
{
static std::string const ret = std::string("do uble");
return ret;
}

// now the main thing stars
template<typena me _First, typename _Second>
struct Base
{
typedef _First First;
typedef _Second Second;

virtual ~Base() {}

Base() { printFirstTempl ateParameter(); }

void
printFirstTempl ateParameter() { std::cout<<"Fir st parameter type:
"<<TypeToString <First>()<<std: :endl; }

virtual void
someOtherFuncti on() { std::cout<<"UNI X: dont know what to
do!"<<std::endl ; }
};

template<typena me T>
struct BaseSecedToInt
: public Base<int, T>
{
void
someOtherFuncti on() { std::cout<<"Win doze: dont know what to
do!"<<std::endl ; }
};

template<typena me T>
struct BaseSecedToLong
: public Base<long, T>
{
void
someOtherFuncti on() { std::cout<<"OSX : dont know what to
do!"<<std::endl ; }
};
int main(int argc, char *argv[])
{
Base<double, double> b;
b.someOtherFunc tion();

BaseSecedToInt< double> bi;
bi.someOtherFun ction();

BaseSecedToLong <double> bl;
bl.someOtherFun ction();

return 0;
}
Jul 22 '05 #7
Andre Dajd wrote:
"Lionel B" <go****@lionelb .com> wrote in message news:<10******* *************** @f14g2000cwb.go oglegroups.com> ...
Greetings.


<snip>

You may solve your issues by combining templates with
inheritance. You write one (or many) base template class(es)
and then subclass from them with reduced set of template parameters.
This will pull allvirtuals form the base which will be automatically
specialized, but which you will still be able to overwrite.


I had thought of trying something like that (although from what you
point out below it would not neccesarilly have worked, I suspect) and
rejected it on the grounds of: (a) my class is very low-level and
supposed to be super-efficient - could not afford the overhead of
virtual functions - and (b) it would entail horrifically obscure code,
as your example amply demonstrates ;)
This will not always work, precisely because ALL base class
function will be specialized in this approach (following standard
instantiation rules), which may result in some illegal code being
generated. That's why one may need to finer slice the superclass
into several classes.
This would probably be a nightmare in my case.
Also, this will work only when the context will allow you to use
the inherited methods polymorphically . Eg, it will not work in
constructors.


[...]

Thanks,

--
Lionel B

Jul 22 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
6859
by: Paul MG | last post by:
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()).
2
2411
by: Simon G Best | last post by:
Hello! I have a query regarding explicit specialisation of class templates which are themselves members of class templates. Here's what I want to do: template< class T > struct pink { template< class U > struct floyd;
1
2269
by: Alfonso Morra | last post by:
if I have a class template declared as ff: (BTW is this a partial specialization? - I think it is) template <typename T1, myenum_1 e1=OK, my_enum_2=NONE> class A { public: A(); virtual ~A() ;
6
2807
by: rincewind | last post by:
Hi, can anybody summarise all options for partial template specialization, for all kind of parameters (type, nontype, template)? I *think* I understand options for partial specialization on type parameters - in place of a template argument one can construct arbitrary valid C++ type declaration, more or less like in "typedef" statement. What about nontype parameters? Am I right that you cannot partially
1
1829
by: Nathan Addy | last post by:
I am trying to partially specialize a template in the following way: I have two template classes defined: template <typename T> class Foo { public: Foo(); }; template <typename T>
8
3860
by: Paul Roberts | last post by:
Hi, I'm hoping somebody here can help me with a simple problem of template syntax. Here's an example: template<typename T, int iclass A { static int a;
1
1750
by: Martin | last post by:
I'm trying to make a partial specialization of a class of mine. Can someone please tell me what's wrong with the following code? GCC gives me the error "invalid use of undefined type "class X<int, B>"". template <class A, class B> class X { public: void f(); };
8
2437
by: Rahul | last post by:
Hi, Is there a way to partially specialize only a member function of a template class (not the whole class). e.g. template <typename A, typename B> class Base { public:
9
3465
by: stephen.diverdi | last post by:
Can anyone lend a hand on getting this particular template specialization working? I've been trying to compile with g++ 4.1 and VS 2005. //------------------------------------------------------------------ // my regular glass class A { }; // my templated class
0
8834
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9365
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9212
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9127
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
6664
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5973
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4483
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4748
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2569
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.