Template spezialization

T

Thomas Kowalski

Hi,
I would like to write a template class Polygon<VertexTyp> there vertex
typ can be eigther a pointer or a value typ.

It has an attribute:
std::vector<VertexTyp> vertices;

And a methode:
VertexValueTyp& vertex(int i);
that dereferences vertices internally in case VertexTyp is a pointer
type.

How can I achieve this? Are there any step-by-step guides online?

Thanks in advance,
Thomas Kowalski
 
J

Jakob Bieling

Thomas Kowalski said:
I would like to write a template class Polygon<VertexTyp> there vertex
typ can be eigther a pointer or a value typ.

It has an attribute:
std::vector<VertexTyp> vertices;

And a methode:
VertexValueTyp& vertex(int i);
that dereferences vertices internally in case VertexTyp is a
pointer type.

How can I achieve this? Are there any step-by-step guides online?


The following template and its specialization should give you an
idea:

template <typename T>
class A
{

};

template <typename S>
class A <S*>
{
};

int main ()
{
A <char> aa;
A <char*> ab;
}

You would have to completely reimplement the specialization of the
template class.

There are also ways to move the specialization out of the main class
by using inheritance:

template <typename T>
class special_A
{
// stuff for non-pointers
};

template <typename S>
class special_A <S*>
{

// stuff for pointers
};

template <typename T>
class A : special_A <T>
{
// common functions etc which will be merged
// with the special things
};

int main ()
{
A <char> aa;
A <char*> ab;
}

Now you can provide different implementations in the 'special_A'
template and its specialization and the common stuff in the template
class 'A'. One problem you will face is the ability to cast 'A <char>'
to 'special_A <char>' if you use public inheritance (so your special
functions are exposed). But if you use private inheritance, your special
functions are not available to the user of 'A <char>'. One solution
could be to create a typedef inside the special_A template and its
specialization, which determine the return type of the common function
and use private inheritance:

#include <cstddef>

template <typename T>
class special_A
{
protected:
typedef T ret_t;

ret_t impl ();
};

template <typename S>
class special_A <S*>
{
protected:
typedef S ret_t;

ret_t impl ();
};

template <typename T>
class A : special_A <T>
{
public:
typename special_A <T>::ret_t get_element (std::size_t idx) { return
special_A <T>::impl (); }
};

int main ()
{
A <char> aa;
A <char*> ab;

char ret_aa = aa.get_element (0);
char ret_ab = ab.get_element (0);
}

Now you cannot legally cast the 'A <char>' objects to 'special_A
<char>' and you can still reuse common functions of your class without
having to rewrite them for the specialization.

hth
 
S

Salt_Peter

Thomas said:
Hi,
I would like to write a template class Polygon<VertexTyp> there vertex
typ can be eigther a pointer or a value typ.

It has an attribute:
std::vector<VertexTyp> vertices;

And a methode:
VertexValueTyp& vertex(int i);
that dereferences vertices internally in case VertexTyp is a pointer
type.

How can I achieve this? Are there any step-by-step guides online?

Thanks in advance,
Thomas Kowalski


You have not given any details about VertexTyp. We don't know if you
are dealing with a template parameter that has member functions or is
it just a POD. I'm going to assume a POD for now.

As far as the method is concerned, its actually an operator that you
will prefer dealing with ( operator[] ). Basicly, since Polygon is just
a container wrapping a std::vector, why not match the interface that
std::vector already provides?

Here is an example that uses the name Container instead of Polygon and
a simple int instead of VertexTyp. Lets face it, if you can't get a
templated container handling primitive integers and their pointers
working, how will u be able to get to work with a more complex type?

#include <iostream>
#include <ostream>
#include <vector>

template < typename T >
class Container
{
std::vector< T > v;
public:
Container() : v() { }
Container(size_t sz) : v(sz) { }
~Container() { }
/* member functions */
size_t size() const { return v.size(); }
void push_back( const T& r_t ) { v.push_back(r_t); }
T& operator[]( const unsigned index ) { return v.at(index); }
};

int main()
{
const unsigned sz( 5 );
Container< int > integers(sz); // a vector of 5 integers
Container< int* > pointers; // an empty vector of pointers to int

for ( size_t i = 0; i < integers.size(); ++i )
{
integers = static_cast<int>(i);
pointers.push_back( &integers[ i ] );
}

// test
*pointers[0] = 101;

for ( size_t i = 0; i < integers.size(); ++i )
{
std::cout << pointers << "\t";
std::cout << integers << std::endl;
}
return 0;
}

/*
0x503010 101
0x503014 1
0x503018 2
0x50301c 3
0x503020 4
*/

Remember that your VertexTyp needs to support copy semantics.
 

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

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,228
Latest member
MikeMichal

Latest Threads

Top