473,419 Members | 1,925 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,419 software developers and data experts.

Help with template specialisation syntax

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;
};

template<typename T, int iint A<T, 0>::a = 3;

Here, I'm trying to specialise T for the case where i is 0.

MSVC (8.0) reports this error on the last line: "template argument list
following class template name must list parameters in the order used in
template parameter list".

As far as I can see, the lists *do* list their parameters in the same order!

I've consulted Stroustup (2nd Ed) and the other C++ books I have, but I
can't find a similar partial specialisation example to learn from. In
simpler specialisation examples, they leave out the first parameter list
(giving just template<>), but if I do this, then T isn't recognised
later on in the same line. If I give "typename T" but omit "int i", then
the compiler says I have too few template parameters for T.

What's the proper syntax for this particular kind of specialisation?

Many thanks to anyone who can assist.
--
Paul Roberts
www.m3fe.com

Sep 9 '06 #1
8 3839
Paul Roberts wrote:
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;
};

template<typename T, int iint A<T, 0>::a = 3;

Here, I'm trying to specialise T for the case where i is 0.
[snip]

You are missing the actual specialization of the class:

template < typename T, int i >
class A {
static int a;
};

template < typename T >
class A<T,0{
static int a;
};

template < typename T >
int A<T, 0>::a = 3;

Best

Kai-Uwe Bux
Sep 9 '06 #2

Paul Roberts wrote:
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;
};

template<typename T, int iint A<T, 0>::a = 3;

Here, I'm trying to specialise T for the case where i is 0.

MSVC (8.0) reports this error on the last line: "template argument list
following class template name must list parameters in the order used in
template parameter list".

As far as I can see, the lists *do* list their parameters in the same order!

I've consulted Stroustup (2nd Ed) and the other C++ books I have, but I
can't find a similar partial specialisation example to learn from. In
simpler specialisation examples, they leave out the first parameter list
(giving just template<>), but if I do this, then T isn't recognised
later on in the same line. If I give "typename T" but omit "int i", then
the compiler says I have too few template parameters for T.

What's the proper syntax for this particular kind of specialisation?

Many thanks to anyone who can assist.
--
Paul Roberts
www.m3fe.com
You have to actually write the specialization of the class first, then
initialize its static member:

template<class T, int iclass A
{
static int a;
};

template<class Tclass A<T,0>
{
static int a;
};

template<class Tint A<T, 0>::a = 3;

int main(int argc, char **argv)
{
}

Sep 9 '06 #3
iv********@gmail.com wrote:
You have to actually write the specialization of the class first, then
initialize its static member:

template<class T, int iclass A
{
static int a;
};

template<class Tclass A<T,0>
{
static int a;
};

template<class Tint A<T, 0>::a = 3;

int main(int argc, char **argv)
{
}
Thank you both for your quick replies.

I want the specialized classes A<T, 0>, A<T, 1>, A<T, 2>, ... to all
have the same members (i.e. those in the general A<T, i>). Assuming I
don't want to use inheritance, do I have to duplicate A's entire
contents inside each specialisation? Or is there a shortcut?

Thanks again,

--
Paul Roberts
www.m3fe.com
Sep 9 '06 #4
Paul Roberts wrote:
iv********@gmail.com wrote:
>You have to actually write the specialization of the class first, then
initialize its static member:

template<class T, int iclass A
{
static int a;
};

template<class Tclass A<T,0>
{
static int a;
};

template<class Tint A<T, 0>::a = 3;

int main(int argc, char **argv)
{
}

Thank you both for your quick replies.

I want the specialized classes A<T, 0>, A<T, 1>, A<T, 2>, ... to all
have the same members (i.e. those in the general A<T, i>). Assuming I
don't want to use inheritance, do I have to duplicate A's entire
contents inside each specialisation? Or is there a shortcut?
Why do you want to avoid inheritance? Anyway, if you want the only
difference to be in the initialization of static variables, you could do
something like:

template < typename T, int i >
struct A {
static int a;
};

int init_A_a ( int i ) {
return ( i + 3 );
}

template < typename T, int i >
int A<T,i>::a = init_A_a( i );
#include <iostream>

int main ( void ) {
std::cout << A<int,2>::a << '\n';
}
However, I am curious: what is the underlying problem that this design is
supposed to solve? Maybe there is a different approach altogether.
Best

Kai-Uwe Bux
Sep 9 '06 #5
Kai-Uwe Bux wrote:
<snip>
However, I am curious: what is the underlying problem that this design is
supposed to solve? Maybe there is a different approach altogether.

I'll try to summarise as briefly as possible, but it's still going to be
quite long, so feel free to retract the offer of help if your curiosity
wanes :-)

I am working with a planet-sized fractal terrain with dynamic level of
detail, represented by a binary tree of triangular "patches". I use a
variant of the ROAM algorithm[1] to construct this tree. I have a class
representing such a patch - let's call it TriPatch. The algorithm that
turns a TriPatch into actual rendered triangles can work at one of four
global "density" settings - each higher density level stores more
vertices (call them Points) per patch, so I templated TriPatch as follows:

template<int densityclass TriPatch
{
TriPatch* leftChild, *rightChild;
// ... more common attributes/methods

Point points[SomeFunctionOf(density)];
void GenerateNewPoints();
};

template<int densityvoid TriPatch<0>::GenerateNewPoints()
{
// unique code for density setting 0...
points[0] = Point::GeneratePoint(...);
...
}
....
template<int densityvoid TriPatch<3>::GenerateNewPoints()
{
// unique code for density setting 3...
}

Now, I want to reuse the terrain code to render water (effectively as a
"flat" terrain), sharing the same basic binary tree structure and
operations.

The Points stored inside each TriPatch are generated by a fractal
algorithm (midpoint displacement[2]) that takes surrounding vertices as
input. The vertices store fractal seeds along with their 3D positions.
With water, though, the vertex generation code will not apply a fractal
perturbation, and no fractal parameters will be stored at each vertex.

So, my plan was to create a distinct WaterPoint type (with its own
implementation of GenPoint), and to further templatise TriPatch on the
point type:

template<typename PointT, int densityclass TriPatch
{
// as above, except
PointT points[...];
};

Terrain and water binary trees could then be initialised as follows:

const int density = 2;
TriPatch<Point, densitymyTerrain = new TriPatch<Point, density>;
TriPatch<WaterPoint, densitymyWater = new TriPatch<WaterPoint, density>;

The GenerateNewPoints method given above remains the same regardless of
the point type used, since it calls PointT's own GenPoint for the actual
generation. It needs to be specialised only for /density/, hence the
example in my original post where we specialised on the non-type
parameter, while the type parameter remained unspecified.

Now, to achieve my "terrain patch" and "water patch" types I could
simply duplicate the bin-tree structure and associated algorithms, but
since these make up most of the code, and are identical in both cases, I
felt that I should strive for shared code. Since I am potentially
calling methods on many thousands of TriPatches per frame (at 60 frames
per second), I don't want methods like GenerateNewPoints to be virtual
functions. And since the density setting and vertex generation algorithm
for any particular tree of TriPatches is known at compile-time, I
figured this was an ideal situation for templates.

I'm trying to find a solution that maximises performance and code
re-use, while remaining fairly readable. If there is a different
approach that satisfies these criteria, I'd be happy to hear about it!

Thanks if you read this far :-)

--
Paul Roberts
www.m3fe.com

[1] http://www.llnl.gov/graphics/ROAM/
[2] http://www.gameprogrammer.com/fractal.html
Sep 10 '06 #6

Paul Roberts wrote:
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;
};

template<typename T, int iint A<T, 0>::a = 3;

Here, I'm trying to specialise T for the case where i is 0.

MSVC (8.0) reports this error on the last line: "template argument list
following class template name must list parameters in the order used in
template parameter list".

As far as I can see, the lists *do* list their parameters in the same order!
A straightforward solution would be to create a "helper" class
template, say, ConstantA, to specify the appropriate value for "a" for
each int value:

template <int N>
struct ConstantA;

template <>
struct ConstantA<0>
{
const static int value = 3;
};

template <>
struct ConstantA<1>
{
const static int value = 8;
};

and so forth. Then declare the general class template for A, using
ConstantA to supply a's value:

template <int N>
struct A
{
static const int a = ConstantA<N>::value;
...
};

Greg

Sep 10 '06 #7
Greg wrote:
A straightforward solution would be to create a "helper" class
template, say, ConstantA, to specify the appropriate value for "a" for
each int value:
<snip>

I now have a working solution based on your suggestion. Thanks!

--
Paul Roberts
www.m3fe.com
Sep 11 '06 #8

Paul Roberts wrote:
template<typename T, int iclass A
{
static int a;
};

template<typename T, int iint A<T, 0>::a = 3;
To specialize a template you put the parameters the new specialization
takes in the first list and pass the parameters you want to the
original template. So, if you are trying to default i to 0 you can
think of it as creating a new template that accepts one typename
parameter:

template < typename T >
// Now pass the appropriate arguments to the template you are
specializing:
int A<T, 0>::a = 3;

Note that if you are specializing fully, as in no arguments left, you
would have a "new" template that accepts no parameters:

template <>
// and then pass the appropriate arguments to the original template:
int A<int, 0>::a = 3;

And of course your standard definition (the one for everything
unspecialized) is also a "new" template that accepts the same amount of
parameters as the old:

template < typename T, int i >
int A<T, i>::a = 3;

Now, you aren't really creating "new" templates (hense the quotes) but
it can help to think of it that way. The point is that the list to
your template definition is the parameters that are left to take and
then you pass the necissary parameters, including ones that you don't
take in and the ones you do, off to the template you are specializing.

Sep 11 '06 #9

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

Similar topics

17
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...
2
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 { ...
12
by: Tim Clacy | last post by:
Your expertise will be appreciated... Here's a general templatised class; all specialisations of this class should have a pointer to a specialisation of the same, templatised type: ...
2
by: Martin MacRobert | last post by:
Hi, I'm trying to make a specialisation of a template function, so that the second parameter accepts scalar types only (int,double,float etc.). How can I do this without writing an explicit...
7
by: Lionel B | last post by:
Greetings. The following code compiles ok and does what I'd expect it to do: ---------- START CODE ---------- // test.cpp
5
by: Amit | last post by:
Greetings all, I am writing some code somehwat similar to the test code I have below. I am having a variety of issues with template specialization. I am not sure if this is related to something...
1
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>
4
by: Howard Gardner | last post by:
// I think that there is no way to write the template "cant_write_me" in // this example. Would love to be wrong. // one of many approaches that won't work template< template< typename class...
4
by: Adam Nielsen | last post by:
Hi everyone, I've having some trouble trying to specialise a template. My original code, with one typename, worked: template <typename T> class MyClass { private: T data;
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
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,...
0
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...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
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...
0
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...

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.