templates

C

Chameleon

Is this possible?

template<int DIMENSIONS>
struct Vector
{
union {
long double elements[DIMENSIONS];
struct {long double x;
long double y;
____if DIMENSIONS==3
long double z;
____else
static const long double z = 0;
____endif
};
};
};


thanks for your time!
 
Joined
Jan 3, 2011
Messages
6
Reaction score
0
This forum has code tags to help with formatting code snippets. Please help others understand sections of code by USING them. :)

Code:
template<int DIMENSIONS>
struct Vector
{
	union
	{
		long double elements[DIMENSIONS];
		struct
		{
			long double x;
			long double y;
			____if DIMENSIONS==3
				long double z;
			____else
				static const long double z = 0;
			____endif
		};
	};
};

Principally, this is doable, though not quite using the syntax you've used. To get the if-else type behavior for your template declaration, you can use template specialization. You'd provide one general template for use with all possible dimension PLUS one specialization for that special case where DIMENSIONS == 3.


Example program:

Code:
#include <iostream>


template < int DIMENSIONS >
struct Vector
{
	union MyUnion
	{
		long double elements[ DIMENSIONS ];

		struct NestedStruct
		{
			long double x;
			long double y;

			static const long double z;
		};

		NestedStruct n;
	};

	MyUnion u;
};

template < int DIMENSIONS > const long double Vector< DIMENSIONS >::MyUnion::NestedStruct::z = 0.0;


template <>
struct Vector< 3 >
{
	union MyUnion
	{
		long double elements[ 3 ];

		struct NestedStruct
		{
			long double x;
			long double y;

			long double z;
		};

		NestedStruct n;
	};

	MyUnion u;
};


int main()
{
	// uses the non-static z in our specialization for 3 dimensions
	Vector< 3 > bb;
	bb.u.n.z = 2.6e4;
	std::cout << "bb.u.n.z = " << bb.u.n.z << std::endl;

	// uses the static z in all other specializations
	std::cout << "Vector< 5 >::MyUnion::NestedStruct::z = " << Vector< 5 >::MyUnion::NestedStruct::z << std::endl;

	return 0;
}
 
Last edited:
U

Ulrich Eckhardt

Chameleon said:
Is this possible?

template<int DIMENSIONS>
struct Vector
{
union {
long double elements[DIMENSIONS];
struct {long double x;
long double y;
____if DIMENSIONS==3
long double z;
____else
static const long double z = 0;
____endif
};
};
};

Yes, you can specialize your class template for two and three dimensions.
Of course, this requires you to rewrite the rest of the code you omitted
for the general template and all specializations. You can avoid that by
using derivation, possibly in combination with CRTP.

Cheers!

Uli
 
A

Alf P. Steinbach /Usenet

* Chameleon, on 08.01.2011 03:17:
Is this possible?

template<int DIMENSIONS>
struct Vector
{
union {
long double elements[DIMENSIONS];
struct {long double x;
long double y;
____if DIMENSIONS==3
long double z;
____else
static const long double z = 0;
____endif
};
};
};


<code>
template< int n >
class Vector
{
private:
double values_[n];

public:
Vector(): values_() {}

double& operator[] ( int i ) { return values_; }
double operator[] ( int i ) const { return values_; }

double& x() { return values_[0]; }
double x() const { return values_[0]; }

double& y() { return values_[1]; }
double y() const { return values_[1]; }

double& z();
double z() const;
};

template< int n >
double& Vector<n>::z()
{
char noZForThisDimension[2*(n - 3) + 1];
throw 666;
}

template<>
double& Vector<3>::z() { return values_[2]; }

template< int n >
double Vector<n>::z() const
{
static double const defaultZ = 0.0;
return defaultZ;
}

template<>
double Vector<3>::z() const { return values_[2]; }


int main()
{
Vector<2> v;

v.x();
v.y();
//v.z();
}
</code>


Cheers & hth.,

- Alf
 
C

Chameleon

Στις 08/01/2011 05:52, ο/η Alf P. Steinbach /Usenet έγÏαψε:
* Chameleon, on 08.01.2011 03:17:
Is this possible?

template<int DIMENSIONS>
struct Vector
{
union {
long double elements[DIMENSIONS];
struct {long double x;
long double y;
____if DIMENSIONS==3
long double z;
____else
static const long double z = 0;
____endif
};
};
};


<code>
template< int n >
class Vector
{
private:
double values_[n];

public:
Vector(): values_() {}

double& operator[] ( int i ) { return values_; }
double operator[] ( int i ) const { return values_; }

double& x() { return values_[0]; }
double x() const { return values_[0]; }

double& y() { return values_[1]; }
double y() const { return values_[1]; }

double& z();
double z() const;
};

template< int n >
double& Vector<n>::z()
{
char noZForThisDimension[2*(n - 3) + 1];
throw 666;
}

template<>
double& Vector<3>::z() { return values_[2]; }

template< int n >
double Vector<n>::z() const
{
static double const defaultZ = 0.0;
return defaultZ;
}

template<>
double Vector<3>::z() const { return values_[2]; }


int main()
{
Vector<2> v;

v.x();
v.y();
//v.z();
}
</code>


Cheers & hth.,

- Alf



thanks!
 
A

Alf P. Steinbach /Usenet

* Chameleon, on 08.01.2011 11:15:

Possibly a bit premature...

Because I forgot to mention a subtlety that you will probably run into.

When you (as I suppose you will) put e.g.

template<>
double& Vector<3>::z() { return values_[2]; }

in a header file, then you may/will encounter multiple definition linker errors.

That's because it's no longer a template: since it's fully specialized (the
standard calls that an "explicit specialization", as I recall) it's just an
ordinary function definition. And you can't have two or more definitions of the
same function, unless the function is "inline". With "inline" you can have
multiple definitions as long as they're in different translation units.

Thus, for use in a header file, add the keyword "inline", like this:

template<>
inline double& Vector<3>::z() { return values_[2]; }

Cheers & hth.,

- Alf
 

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,770
Messages
2,569,586
Members
45,088
Latest member
JeremyMedl

Latest Threads

Top