Template Metaprogramming

P

Protoman

I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work. Here it is:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
};

Sqr sqr;

int main()
{
cout << sqr<10>::RET << endl;
system ("PAUSE");
return 0;
}

By all the websites I've read, this should work absolutely fine. Could
you help me? And, if it's any help, I'm using Bloodshed's Dev-Cpp
v4.9.9.2 compiler.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
V

Victor Bazarov

Protoman said:
I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work.

What seems to be the problem? Read FAQ 5.8, while you're looking for
an answer.
> Here it is:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
};


Sqr sqr;
^^^^^^^
What is that supposed to do? Define an object 'sqr' of type.. which?
'Sqr' is not a class. It's a class template. In order for it to become
a class, you need to supply the template argument.

Sqr said:
int main()
{
cout << sqr<10>::RET << endl;

If 'sqr' is an object, you can't use either <> or :: after it. If it is
not an object, then what is it?

cout << Sqr<10>::RET << endl;
or
cout << sqr.RET << endl;
system ("PAUSE");
return 0;
}

(a) You didn't define the 'RET' static data member. All static data
members need to be defined if they are used outside the class
definition.

(b) You didn't use the static member properly. If you want to use it
through an object, the access is via the . operator (dot), if you
want to use it through the class, then you need the class name
before the scope resolution operator.
By all the websites I've read, this should work absolutely fine.

Please list the URLs so we could include them into the list of web sites
to avoid.
> Could
you help me? And, if it's any help, I'm using Bloodshed's Dev-Cpp
v4.9.9.2 compiler.

V
 
M

msalters

Protoman schreef:
I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work. Here it is:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
};

Sqr sqr;

int main()
{
cout << sqr<10>::RET << endl;
system ("PAUSE");
return 0;
}

With template metaprogramming, you manipulate types, not objects. Of
course, a type cannot be modified, so it has to be right the first
time.
Your Sqr template is a good example. If you create the type Sqr<10>,
the constant Sqr<10>::RET is set to 100.

However, you try to use Sqr (which isn't a type) to create an object
sqr, and then you try to modify the object inside main. That doesn't
work, but the object simply isn't needed. Use the type Sqr<10>.

HTH,
Michiel Salters


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
U

Ulrich Eckhardt

Protoman said:
I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work. Here it is:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
};

Leave ALL_UPPERCASE for macros, and only for those. Just an advise though.

This is already wrong, you cannot create objects of a tempate type, only
objects of a template-instantiation (I only hope that the terminology is
right).
cout << sqr<10>::RET << endl;

As already said, above should not even compile, so I wonder why you post
even more code. However said:
system ("PAUSE");

Nonportable. Ugly.
std::string dummy;
And, if it's any help, I'm using Bloodshed's Dev-Cpp
v4.9.9.2 compiler.

That's not a compiler but an IDE. The compiler in use there is GCC.

Uli


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
M

Markus Moll

Hi
template<int n>
class Sqr
{
public:
static const int RET = n*n;
};

Sqr sqr;

Sqr is a template-id, so this makes no sense.
int main()
{
cout << sqr<10>::RET << endl;

so this should read: said:
system ("PAUSE");
return 0;
}

By all the websites I've read, this should work absolutely fine.

Where have you been reading?


Markus


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
N

noahwoo

Maybe your idea can be expressed like this :
(Tested by gcc)
#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;

};

// Sqr<10> sqr;

int main()
{
cout << Sqr<10>::RET << endl;
system ("PAUSE");
return 0;
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
A

Anthony Williams

Protoman said:
I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work. Here it is:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
};

Sqr sqr;

Sqr on its own is the name of a template. To create an object, you need a
int main()
{
cout << sqr<10>::RET << endl;

If you create an object sqr above, then you don't need the <10>
here. Alternatively said:
system ("PAUSE");
return 0;
}

HTH

Anthony
--
Anthony Williams
Software Developer

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
A

Andy

I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work. Here it is:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;

Instead of the "static const int RET" use the typical idiom:
enum { square_value = n*n };
};

Sqr sqr;

This is incorrect. Sqr is a class template, you cannot instantiate it.
You must provide the necessary template arguments and instantiate a
int main()
{
cout << sqr<10>::RET << endl;

sqr said:
system ("PAUSE");
return 0;
}

By all the websites I've read, this should work absolutely fine. Could

Which websites are these?
you help me? And, if it's any help, I'm using Bloodshed's Dev-Cpp
v4.9.9.2 compiler.
With the modifications it works on Dev-Cpp 4.9.9.2.

Cheers,
Andy


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
G

Greg

Protoman said:
I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work. Here it is:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
};

Sqr sqr;

int main()
{
cout << sqr<10>::RET << endl;
system ("PAUSE");
return 0;
}

By all the websites I've read, this should work absolutely fine. Could
you help me? And, if it's any help, I'm using Bloodshed's Dev-Cpp
v4.9.9.2 compiler.

I don't see how this code could have compiled. The declaration of "sqr"
has as its type "Sqr" but without an int value that is needed as its
template parameter. This line can be deleted moreover since "sqr" is
not needed for the purposes of this example. Just change the output
line to use the template class name:

cout << Sqr<10>::RET << endl1;

will output 100 on any conforming compiler.

Greg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
M

Martin Bonner

Protoman said:
I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work.
You don't explain what you mean by "doesn't work". Compiler error?
Linker error? Runtime crash? Unexpected output? You should also tell
us what the error message / output is (and in the case of unexpected
output, what you expected).

However in this case, I can guess what the problem is.
Here it is:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
Note: This is perfectly valid Standard C++, HOWEVER
a) You should reserved all-caps identifiers for preprocessor macros
b) Some older compilers may have problems with this. The work round
would be to use
enum {value=n*n};
};

Sqr sqr;
This is your problem. You are trying to declare an object (called
'sqr') of type Sqr. The problem is that 'Sqr' is not a type, it is a
template which defines how to create a large number of types. You
*could* use:

Sqr<10> sqr10;

That would declare an an object (called sqr10) of type Sqr<10>.
However, you don't actually need an object at all (that was the point
of the 'static' on the declaration of RET - in this context static
means "associated with the type, not with an individual object of the
type).
int main()
{
cout << sqr<10>::RET << endl;

This is essentially the same problem: you are confused between objects
and templates. You can either write:
Sqr<10>::RET
or
sqr10.RET
(I would prefer the former.)
system ("PAUSE");
Note: I trust you realize this is not portable? (It is completely
unrelated to your problem, and is fine for this toy application, but if
you run the application direct from the command line you won't need it
at all.)
return 0;
}

By all the websites I've read, this should work absolutely fine.
I think you need to read the websites again (or read better ones)!


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
G

Gene Bushuyev

....
Nonportable. Ugly.
std::string dummy;
std::cout << "<enter>\n";
std::getline( std::cin, dummy);

Portable, but still ugly. This would suffice:

std::cerr << "\nPress Enter\n";
std::cin.ignore();

- gene
 
T

tony_in_da_uk

What you're trying to do isn't actually template metaprogramming in any
meaningful sense, as metaprogramming involves templates instantiating
themselves or other templates to implement an algorithm, but I'll
ignore that for now and help you get it working as presented.

Perhaps you should look at the compiler error messages? The simplest
way to get what you've done going is to change "sqr<10>::RET" to
"Sqr<10>::RET", and remove the "Sqr sqr;" line (you'd need Sqr<10>
sqr;" there to get the intended effect, but you don't need an instance
of the templated class in order to use a static member.

Cheers, Tony


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
S

Sasko Mateski

I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work. Here it is:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
};

instead of:
Sqr sqr;

int main()
{
cout << sqr<10>::RET << endl;
system ("PAUSE");
return 0;
}

try just:
int main()
{
cout << Sqr<10>::RET << endl;
system ("PAUSE");
return 0;
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
S

Stefan Chrobot

U=BFytkownik Protoman napisa=B3:
I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program tha= t
uses TMP,it calculates the square of a number, but it doesn't seem to
work. Here it is:

I think you meant:
#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
};

int main()
{
cout << Sqr<10>::RET << endl;
system ("PAUSE");
return 0;
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
D

Dan McLeran

You're declaring a variable of Sqr type with no template arguments.
Here is a solution that works for both MSVC6 and GCC 3.3.1:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
typedef enum {RET = n*n} ResultType;

};


int main()
{
cout << Sqr<10>::RET << endl;
system ("PAUSE");
return 0;
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
M

mlimber

-- Protoman said:
I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work. Here it is:
[snip]
Sqr sqr;
[snip]

The problem is here you are trying to declare an instance of the Sqr<>
class without the template type list. You need to specify the
int-to-be-squared in the typename (e.g., Sqr<10>::RET). In fact,
there's not much sense in your example in declaring an instance of the
class Sqr<> at all -- the square is supposed to be calculated and
inlined at compile-time, so the there's no runtime cost.

Cheers!

M


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
B

Bob Bell

Protoman said:
I've been looking at template metaprogramming. It seems really cool,
make the compiler do most of the work. I have very simple program that
uses TMP,it calculates the square of a number, but it doesn't seem to
work. Here it is:

#include <iostream>
#include <cstdlib>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
};

Sqr sqr;

int main()
{
cout << sqr<10>::RET << endl;
system ("PAUSE");
return 0;
}

By all the websites I've read, this should work absolutely fine. Could
you help me? And, if it's any help, I'm using Bloodshed's Dev-Cpp
v4.9.9.2 compiler.

#include <iostream>
using namespace std;

template<int n>
class Sqr
{
public:
static const int RET = n*n;
};

int main()
{
cout << Sqr<10>::RET << endl;
}

You can't declare a variable of type Sqr, since Sqr isn't a type.

Bob


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
P

Protoman

Here; figure this out:

#include <iostream>
#include <cstdlib>
using namespace std;

template <int n>
struct Sqr
{
enum { square_value = n*n };
};


int main()
{
Sqr<int> sqr;
cout << sqr<10>::square_value << endl;
return 0;
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

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,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top