PDA

View Full Version : Newbie C++ template question




cazador7907
Nov 30, 2010, 06:03 AM
Hi,

I created a very simple program using a template class named Foo (code below). All it does is accept input and then print it out. However, when I attempt to define the class in the main function Foo<char> or Foo<char[]> or even Foo<char*> I receive a variety of errors.

I think that this is because I am attempting to pass in a char array of indeterminate length. So, the question become, how do I set up a template to handle string data?

Thanks in advance!!


-------> Class Foo < ---------

template<typename T>
class Foo
{
public:
T Data;
Foo(T NewData);
void PrintFoo();
};


template<typename T>
Foo<T>::Foo(T NewData)
{
strcpy( Data, NewData);
}

template<typename T>
void Foo<T>::PrintFoo()
{
printf("%s \n", Data);
}


----- > Function Main < --------

#include "string"
#include "main.h"
#include "Foo.h"

using namespace std;

int main(int argc, const char* argv[])
{

char msg[] = "Hello again from Foo!";

Foo<char[]> NewFoo(msg);

printf("Hello World! \n");
NewFoo.PrintFoo();

}



BAADF00D
Nov 30, 2010, 07:38 AM
#include <iostream>

template < typename T >
struct bar {
T data;
bar(T const& x): data(x) { }
void print() const { std::cout << data << std::endl; }
};

int main()
{
char* message = "Hello from bar";
bar<char*> my_function(message);
my_function.print();
}

notes:
-prefer <iostream> and other c++ functions/headers over c-style alternatives if possible.
-your char[] array is really a char*.

cazador7907
Nov 30, 2010, 11:54 AM
Thanks! I will adjust my little program to see what happens. However, so that I know what's going on. It seems to me that the code you posted passing the pointer value in by reference so that X will also point to the message.

Is that correct?

mac2x
Nov 30, 2010, 02:23 PM
Hint: when posting code, using the code tags makes your code a lot easier to read. :)


#include <stdio.h>

int main
{
printf( "Hello World!\n" );

return 0;
}

cazador7907
Dec 1, 2010, 01:46 PM
I simply do not understand what I am doing wrong. Below is the code that I wrote for what I thought would be a simple template test class. The class does exactly one thing: Print a line of text. Everything compiles without error except when I reference the template class in the main program, I receive what I THINK is a linking error. The text of the Error is "Symbol(s) not found."

Please let me know what I'm doing wrong!!

//TFoo.h

#include <iostream>

template<typename T>
class TFoo
{
public:

void PrintTFoo();
};

//TFoo.cpp

#include "TFoo.h"


template<typename T> void TFoo<T>::PrintTFoo()
{
printf("Hello from TFoo.");
}

//main.cpp

#include "main.h"
#include "TFoo.h"

int main( int arga, char* argc[])
{
printf("Hello World. A template test.\n\n");

typedef TFoo<int> intTFoo;

intTFoo newTFoo;
newTFoo.PrintTFoo(); <---- THIS IS WHERE THE ERROR IS REPORTED

}

lloyddean
Dec 1, 2010, 02:04 PM
What happens when you remove '#include "main.h"'?

cazador7907
Dec 1, 2010, 04:02 PM
Same error.

I hate to say this but, in .NET creating a simple template class is much much easier. That said, I really want to figure this out.

lloyddean
Dec 1, 2010, 04:34 PM
After choosing a C++ command line tool based project I pasted the following over the contents of the projects "main.cpp" contents, after which it compiled and ran without problems.


//TFoo.h

#include <iostream>

template<typename T>
class TFoo
{
public:

void PrintTFoo();
};

//TFoo.cpp

//#include "TFoo.h"


template<typename T> void TFoo<T>::PrintTFoo()
{
printf("Hello from TFoo.");
}

//main.cpp

//#include "main.h"
//#include "TFoo.h"

int main( int arga, char* argc[])
{
printf("Hello World. A template test.\n\n");

typedef TFoo<int> intTFoo;

intTFoo newTFoo;
newTFoo.PrintTFoo();

}

chown33
Dec 1, 2010, 05:25 PM
After choosing a C++ command line tool based project I pasted the following over the contents of the projects "main.cpp" contents, after which it compiled and ran without problems.


This suggests there is some funky or invisible character in the OP's file that is causing the failure. It would be a good idea to inspect the binary data in the file using a hex-dump tool.

At the Terminal command-line, there is hexdump. See 'man hexdump'.

Others that don't require Terminal:
HexFiend http://ridiculousfish.com/hexfiend/
0xED http://www.suavetech.com/0xed/0xed.html

It would be another good idea to post the actual hex dump of the file, from the vicinity of where the error occurs.

SidBala
Dec 2, 2010, 01:32 AM
Same error.

I hate to say this but, in .NET creating a simple template class is much much easier. That said, I really want to figure this out.

Haha, I used to be a hardcore C++ fanatic. But after using C# for almost a year now, I don't think I can ever go back. C++ just seems so ugly and untidy.

gnasher729
Dec 2, 2010, 03:25 AM
I simply do not understand what I am doing wrong. Below is the code that I wrote for what I thought would be a simple template test class. The class does exactly one thing: Print a line of text. Everything compiles without error except when I reference the template class in the main program, I receive what I THINK is a linking error. The text of the Error is "Symbol(s) not found."

Please let me know what I'm doing wrong!!

Here's what you are doing wrong: Your compiler sees no reason to instantiate the template. While compiling the template, it has no reason to instantiate it, and when compiling main, it can't. You actually have to put the template code itself into the header file, or put it into a file that is included from the header file and not compiled separately.

BAADF00D
Dec 2, 2010, 07:14 AM
//TFoo.h

#include <iostream>

template<typename T>
class TFoo
{
public:

void PrintTFoo();
};
#include "TFoo.cpp"

//TFoo.cpp

#include "TFoo.h"


template<typename T> void TFoo<T>::PrintTFoo()
{
printf("Hello from TFoo.");
}

//main.cpp

#include "main.h"
#include "TFoo.h"

int main( int arga, char* argc[])
{
printf("Hello World. A template test.\n\n");

typedef TFoo<int> intTFoo;

intTFoo newTFoo;
newTFoo.PrintTFoo(); <---- THIS IS WHERE THE ERROR IS REPORTED

}[/QUOTE]

Detrius
Dec 2, 2010, 07:21 AM
Here's what you are doing wrong: Your compiler sees no reason to instantiate the template. While compiling the template, it has no reason to instantiate it, and when compiling main, it can't. You actually have to put the template code itself into the header file, or put it into a file that is included from the header file and not compiled separately.

Bingo. Template implementations go in header files too. However, further down the line, you'll have to take into account when the template gets instantiated, and you'll have to make sure it happens only once, but that's a different beast.

On top of this, the OP's code is a really really bad example of a template. It's written with the expectation that it will only be giving a string as a template parameter. This is why the recommendation was giving to use iostreams instead of printf, as printf needs to know the type when you use it, but iostreams have overloaded functions/operators, so they can work with any type you give them.

BAADF00D
Dec 2, 2010, 07:32 AM
Same error.

I hate to say this but, in .NET creating a simple template class is much much easier. That said, I really want to figure this out.

c#/.net uses generics, which is a different can of fish. Generics work at run-time. Templates, on the other hand, are just instructions to the compiler to "evaluate then copy and paste" based on your instructions. They are both useful, but not equivalent.

With templates, you need to place the include in the header for the implementation, rather than the other way around. You also have to place inclusion guards, using #pragma once, or #ifndef __xyz__ etc. The easiest way to do this all, is to place both the definition and the implementaion in the same file, instead of splitting them up into two.

There is a decent tutorial at http://www.cplusplus.com/doc/tutorial/templates/

BAADF00D
Dec 2, 2010, 07:39 AM
Thanks! I will adjust my little program to see what happens. However, so that I know what's going on. It seems to me that the code you posted passing the pointer value in by reference so that X will also point to the message.

Is that correct?

Yes. We've used a reference to avoid having to check the pointer for validity - pointers can be null, dangling etc, but your compiler will always check that references are valid before your method is called, usually at compile-time.
Also, being c++, we use "const" to specify which bits are supposed to change and which bits are read-only. This makes the code more readable, and prevents mistakes later on.