(Simple?) template problem

L

Leon

I'm having a bit of a template-problem, and I was wondering if you
guru's know what I'm doing wrong here...

I want to create a Vertex class that supports a toPoint() method. Now,
in my case there are 2 ways of calculating toPoint(), and I want to be
able to choose (at compile time) this method in a flexible way.
Therefore, I want to template this Vertex class.
For example, when I create a Vertex<fixed_tag> I want the 'fixed'
toPoint()-method to be used, whereas when I create a
Vertex<interval_tag>, it should use the 'interval' variant.

What I've done so far is this:

//--------------------------
struct fixed_tag{};
struct interval_tag{};

template<class S>
class Vertex{
//
//Member-vars, constructor e.d.
//

template<fixed_tag>
Point toPoint() const;

template<interval_tag>
Point toPoint() const;

};

//Implementation

template<fixed_tag>
Point Vertex::toPoint() const{
//Calculate and return fixed point
}

template<interval_tag>
Point Vertex::toPoint() const{
//Calculate and return interval point
}

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

Needless to say, the above code doesn't compile properly (VS.NET), and
I've tried quite a few variants on this, but I just can't seem to get
it *right*...

Who can tell me what I'm doing wrong here?
Thanks.
 
?

=?iso-8859-1?Q?Joaqu=EDn=20M=AA=20L=F3pez=20Mu=F1o

Leon ha escrito:
I'm having a bit of a template-problem, and I was wondering if you
guru's know what I'm doing wrong here...

I want to create a Vertex class that supports a toPoint() method. Now,
in my case there are 2 ways of calculating toPoint(), and I want to be
able to choose (at compile time) this method in a flexible way.
Therefore, I want to template this Vertex class.
For example, when I create a Vertex<fixed_tag> I want the 'fixed'
toPoint()-method to be used, whereas when I create a
Vertex<interval_tag>, it should use the 'interval' variant.

What I've done so far is this:

Seems to me like you're trying to specialize Vertex::toPoint,
but C++ does not allow to specialize a single memfun. Several
alternatives come to mind:

1. Specialize Vertex (the whole class) for both fixed_tag and
interval_tag. This forces you to duplicate all the common code.
Not good.
2. Factor the common code into a base class (say VertexBase) and
then proceed as in 1.
3. If you don't envision future variants of toPoint, the following is
a common idiom to do a compile-time selection of the implementation
of a memfun:

struct Point{};

struct fixed_tag{};
struct interval_tag{};

template<class S>
class Vertex{
public:
//
//Member-vars, constructor e.d.
//

Point toPoint() const
{
return toPoint(S()); // forwards to the appropriate impl
}

private:
Point toPoint(const fixed_tag&) const;
Point toPoint(const interval_tag&) const;
};

//Implementation

template<class S>
Point Vertex<S>::toPoint(const fixed_tag&) const{
//Calculate and return fixed point
return Point();
}

template<class S>
Point Vertex<S>::toPoint(const interval_tag&) const{
//Calculate and return interval point
return Point();
}

int main()
{
Vertex<fixed_tag> v;
v.toPoint();

Vertex<interval_tag> v2;
v2.toPoint();
}

Hope this helps,

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
 
?

=?iso-8859-1?Q?Joaqu=EDn=20M=AA=20L=F3pez=20Mu=F1o

Leon ha escrito:
I'm having a bit of a template-problem, and I was wondering if you
guru's know what I'm doing wrong here...

I want to create a Vertex class that supports a toPoint() method. Now,
in my case there are 2 ways of calculating toPoint(), and I want to be
able to choose (at compile time) this method in a flexible way.
Therefore, I want to template this Vertex class.
For example, when I create a Vertex<fixed_tag> I want the 'fixed'
toPoint()-method to be used, whereas when I create a
Vertex<interval_tag>, it should use the 'interval' variant.

What I've done so far is this:

Disregard my previous post, you *can* specialize the toPoint
memfun:

struct Point{};

struct fixed_tag{};
struct interval_tag{};

template<typename S>
class Vertex{
public:
//
//Member-vars, constructor e.d.
//

Point toPoint() const;
};

//Implementation

template<>
Point Vertex<fixed_tag>::toPoint() const{
//Calculate and return fixed point
return Point();
}

template<>
Point Vertex<interval_tag>::toPoint() const{
//Calculate and return fixed point
return Point();
}

int main()
{
Vertex<fixed_tag> v;
v.toPoint();

Vertex<interval_tag> v2;
v2.toPoint();
}

Sorry about my previous response.

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
 
R

Rob Williscroft

Leon wrote in in
comp.lang.c++:
I want to create a Vertex class that supports a toPoint() method. Now,
in my case there are 2 ways of calculating toPoint(), and I want to be
able to choose (at compile time) this method in a flexible way.
Therefore, I want to template this Vertex class.
For example, when I create a Vertex<fixed_tag> I want the 'fixed'
toPoint()-method to be used, whereas when I create a
Vertex<interval_tag>, it should use the 'interval' variant.

/* wherever possible post compilable code
*/
struct Point {};

struct fixed_tag{};
struct interval_tag{};

template<class S>
class Vertex{
//
//Member-vars, constructor e.d.
//

public:

Point toPoint() const;
};

/* Provide explicit specialization's for interval_tag and fixed_tag
*/

template<>
Point Vertex< fixed_tag >::toPoint() const
{
//Calculate and return fixed point
return Point();
}

template<>
Point Vertex< interval_tag >::toPoint() const
{
//Calculate and return interval point
return Point();
}


/* Test
*/

int main()
{
Vertex< fixed_tag > ft;

ft.toPoint();

Vertex< interval_tag > it;

it.toPoint();
}


HTH.

Rob.
 
R

Rob Williscroft

Joaquín Mª López Muñoz wrote in in
comp.lang.c++:
Seems to me like you're trying to specialize Vertex::toPoint,
but C++ does not allow to specialize a single memfun. Several
alternatives come to mind:

In this case toPoint() doesn't need to be a template-member and
can be specialized (see my other reply in this thread).

Also the rule is that a template's template-member can't be
specialized unless the surrounding template is also specialized
(though this doesn't mean the body, see below and examples).
1. Specialize Vertex (the whole class) for both fixed_tag and
interval_tag. This forces you to duplicate all the common code.
Not good.

AFAICT there is no need to specialize the class itself inorder
to specialize a member, though I belive some compilers wrongly
require this.

Can do example
==============

#include <iostream>
#include <ostream>

struct X
{
template < typename T > void f();
};


template < typename T >
void X::f()
{
std::cout << "T\n";
}

template <>
void X::f< int >()
{
std::cout << "int\n";
}


int main()
{
using namespace std;

X x;

x.f<double>();
x.f<int>();
}


Template Example
================

#include <iostream>
#include <ostream>

template < typename U >
struct X
{
template < typename T > void f();
};


template < typename U >
template < typename T >
void X< U >::f()
{
std::cout << "T\n";
}

template <>
template <>
void X< int >::f< int >()
{
std::cout << "int\n";
}


int main()
{
using namespace std;

{
X< double > x;

x.f<double>();
x.f<int>();
}
{
X< int > x;

x.f<double>();
x.f<int>();
}
}

Can't do Example
================

Change the 2nd specialization above too:

template < typename U >
template <>
void X< U >::f< int >()
{
std::cout << "int\n";
}

There is probably some really good reason this can't be done
(other than "the standard says so" which is always good), but
I don't know what it is ?

Rob.
 
?

=?iso-8859-1?Q?Joaqu=EDn=20M=AA=20L=F3pez=20Mu=F1o

Rob Williscroft ha escrito:
Joaquín Mª López Muñoz wrote in in
comp.lang.c++:


In this case toPoint() doesn't need to be a template-member and
can be specialized (see my other reply in this thread).

Yes, you're right. I posted a revised answer shortly after I
realized my error.

[...]
Can't do Example
================

Change the 2nd specialization above too:

template < typename U >
template <>
void X< U >::f< int >()
{
std::cout << "int\n";
}

There is probably some really good reason this can't be done
(other than "the standard says so" which is always good), but
I don't know what it is ?

I remember reading in Vandevoorde & Josutti's book that the
commitee simply dismissed this possibility as they thought it was
too difficult to implement. Curiously enough, MSVC++ 6.0
allows it (though only in inlined form, if I'm not wrong.)

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
 
P

puppet_sock

Joaquín Mª López Muñoz said:
Seems to me like you're trying to specialize Vertex::toPoint,
but C++ does not allow to specialize a single memfun. Several
alternatives come to mind:

1. Specialize Vertex (the whole class) for both fixed_tag and
interval_tag. This forces you to duplicate all the common code.
Not good.
2. Factor the common code into a base class (say VertexBase) and
then proceed as in 1.
3. If you don't envision future variants of toPoint, the following is
a common idiom to do a compile-time selection of the implementation
of a memfun:
[snip]

I can think of a variation. The code that is to go with
the toPoint call could go in another class. Then the
template could have two template params, one the class
that is to be operated on, the other the class that holds
the toVertex implementation. Then instead of

template<class S>
class Vertex{
etc.

you would have

template<class S,class T>
class Vertex{
etc.

where you would pick T from some (small) set of classes each
of which held a particular toPoint implementation. Several
ways you could go from there. Questions like, when to use
friends, do you want static functions in the T's, etc.
Socks
 
L

Leon

Joaquín Mª López Muñoz said:
Disregard my previous post, you *can* specialize the toPoint
memfun:

struct Point{};

struct fixed_tag{};
struct interval_tag{};

template<typename S>
class Vertex{
public:
//
//Member-vars, constructor e.d.
//

Point toPoint() const;
};

//Implementation

template<>
Point Vertex<fixed_tag>::toPoint() const{
//Calculate and return fixed point
return Point();
}

template<>
Point Vertex<interval_tag>::toPoint() const{
//Calculate and return fixed point
return Point();
}

int main()
{
Vertex<fixed_tag> v;
v.toPoint();

Vertex<interval_tag> v2;
v2.toPoint();
}

Sorry about my previous response.

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo

Exactly, that was what I was trying to do! Thanks go to you and Rob
Williscroft, who also posted the same solution :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,169
Messages
2,570,920
Members
47,464
Latest member
Bobbylenly

Latest Threads

Top