Jump to content
  • Advertisement
Sign in to follow this  
exorcist_bob

problems with template metaprogramming

This topic is 4354 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I am having some problems with template metaprogramming in vc++. I am trying to get the following to compile:
#include <iostream>
#include <tchar.h>

#pragma inline_depth(255)
#pragma inline_recursion(on)

using namespace std;

template<double R> struct Sine
{
	enum { MaxTerms = 10 };
	static inline double sin()
	{
		return R * Series<R, 0, MaxTerms>::val();
	}
};

template <double R, int I, int MaxTerms> struct Series
{
	enum
	{
		Continue = I + 1 != MaxTerms,
		NxtI = ( I + 1 ) * Continue,
		NxtMaxTerms = MaxTerms * Continue
	};

	static inline double val()
	{
		return 1 - R*R/(2.0 * I + 2.0)/(2.0 * I + 3.0)*Series<R*Continue, NxtI, NxtMaxTerms>::val();
	};
};

template <> struct Series<0.0, 0, 0>
{
	static inline double val() { return 1.0; };
};

#define SineVal( r ) Sine<r>::sin()


int _tmain(int argc, _TCHAR* argv[])
{
	char ch;
	double val = 5.0;
	cout << SineVal(val) << endl;
	cin >> ch;
	return 0;
}

But i'm getting the following errors:

error C2993: 'double' : illegal type for non-type template parameter 'R'
error C2993: 'double' : illegal type for non-type template parameter 'R'


PS This came straight from Game Programming Gems, and was compiled using visual c++ 2005 express edition. Thanks for any assistance, exorcist_bob

Share this post


Link to post
Share on other sites
Advertisement
1. template<double R> struct Sine { ... };
I don't believe any current compiler is supporting non-integral values as template parameters. That is: int, char, bool - yes, but float, double - nope.
EDIT: See Section 14.1 4 of The standard.
EDIT2: Section 14.1 7 of The standard explicitly disallows floating point values as template parameters.

2. #define SineVal( r ) Sine<r>::sin()
In expression: SineVal(val), val has to be a compile-time expression. Like: enum { val=5 }, or #define val 5. If 1. wasn't in the way, you could get away with SineVal(5.0).

Share this post


Link to post
Share on other sites
MSVC 6 will allow for double and float non-type template arguments. For standard C++, you can use references to const double as non-type template arguments. It gets pretty ugly in instantiation for it to work, but compilers will generally expand the expressions out at compile time.

Share this post


Link to post
Share on other sites
I dont really get what you are doing here,

Template parameters are not allowed to have a type (except class) is my understanding. This doesn't look like good C++ programming to me. Anyone?

Greetings.

Share this post


Link to post
Share on other sites
I can't make those const, since I'm returning values. But if I make them references, I get these errors:

1>codetester.cpp(34) : error C2440: 'specialization' : cannot convert from 'double' to 'double &'
1>codetester.cpp(45) : error C2440: 'specialization' : cannot convert from 'double' to 'double &'
1>codetester.cpp(45) : error C2440: 'specialization' : cannot convert from 'int' to 'double &'
1>codetester.cpp(45) : see reference to class template instantiation 'Sine<R>' being compiled
1> with
1> [
1> R=0
1> ]
1>codetester.cpp(45) : error C2973: 'Sine' : invalid template argument 'int'
1>(16) : see declaration of 'Sine'

Thanks for the help!
exorcist_bob

Share this post


Link to post
Share on other sites
Quote:
Original post by Limitz
Template parameters are not allowed to have a type (except class) is my understanding. This doesn't look like good C++ programming to me. Anyone?


No, C++ allows several types of non-type template arguments including, roughly in order of most frequently encountered to least frequently encountered: constant integral expressions, enumerations, objects or functions with external linkage, addresses of objects and functions and pointer to members.

Share this post


Link to post
Share on other sites
i think the template should recieve const variable.
so I think this is wrong.

double val = 5.0; // should be const double val = 5.0;
cout << SineVal(val) << endl;


as far as i remember, template is generate on compile time. and if you don't use const variable, then it will compile error.
I think metaprogramming is not used for run time calculation, instead it is used for defining constants.

Share this post


Link to post
Share on other sites
Quote:
Original post by EkEk
i think the template should recieve const variable.
so I think this is wrong.
*** Source Snippet Removed ***
as far as i remember, template is generate on compile time. and if you don't use const variable, then it will compile error.
I think metaprogramming is not used for run time calculation, instead it is used for defining constants.


Just got done with that, thanks! However, I'm getting the same errors.

Here's the updated source:


#include <iostream>
#include <tchar.h>
#include <cmath>

#pragma inline_depth(255)
#pragma inline_recursion(on)

using namespace std;

template<double& R> struct Sine
{
enum { MaxTerms = 10 };
static inline double sin()
{
return R * Series<R, 0, MaxTerms>::val();
}
};

template <double& R, int I, int MaxTerms> struct Series
{
enum
{
Continue = I + 1 != MaxTerms,
NxtI = ( I + 1 ) * Continue,
NxtMaxTerms = MaxTerms * Continue
};

static inline double val()
{
return 1 - R*R/(2.0 * I + 2.0)/(2.0 * I + 3.0)*Series<R*Continue, NxtI, NxtMaxTerms>::val();
};
};

template <> struct Series<0.0, 0, 0>
{
static inline double val() { return 1.0; };
};

#define SineVal( r ) Sine<r>::sin()

int _tmain(int argc, _TCHAR* argv[])
{
char ch;
cout << Sine<5.0>::sin() << endl;
cout << sin(5.0) << endl;
cin >> ch;
return 0;
}




1>------ Build started: Project: CodeTester, Configuration: Debug Win32 ------
1>Compiling...
1>CodeTester.cpp
1>f:\cross-platform object-oriented development engine\codetester\codetester.cpp(35) : error C2440: 'specialization' : cannot convert from 'double' to 'double &'
1>f:\cross-platform object-oriented development engine\codetester\codetester.cpp(44) : error C2440: 'specialization' : cannot convert from 'double' to 'double &'
1>f:\cross-platform object-oriented development engine\codetester\codetester.cpp(44) : error C2440: 'specialization' : cannot convert from 'int' to 'double &'
1> f:\cross-platform object-oriented development engine\codetester\codetester.cpp(44) : see reference to class template instantiation 'Sine<R>' being compiled
1> with
1> [
1> R=0
1> ]
1>f:\cross-platform object-oriented development engine\codetester\codetester.cpp(44) : error C2973: 'Sine' : invalid template argument 'int'
1> f:\cross-platform object-oriented development engine\codetester\codetester.cpp(17) : see declaration of 'Sine'
1>Build log was saved at "file://f:\Cross-Platform Object-Oriented Development Engine\CodeTester\Debug\BuildLog.htm"
1>CodeTester - 4 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 13 up-to-date, 0 skipped ==========



Thanks,
exorcist_bob

Share this post


Link to post
Share on other sites
Reference non-type template paramters must be bound to variables with external linkage. 5.0 is a double literal, which is not a variable with external linkage.

double five = 5.0;

int _tmain(int argc, _TCHAR* argv[])
{
// blah blah blah
cout << Sine<five>::sin() << endl;
// blah blah blah

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!