Newbie C++ template question

Discussion in 'Mac Programming' started by cazador7907, Nov 30, 2010.

  1. cazador7907, Nov 30, 2010
    Last edited by a moderator: Nov 30, 2010

    macrumors newbie

    Joined:
    Nov 8, 2010
    #1
    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!!

    Code:
    -------> 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();
    
    }
     
  2. BAADF00D, Nov 30, 2010
    Last edited by a moderator: Nov 30, 2010

    macrumors newbie

    Joined:
    Nov 30, 2010
    #2
    try...

    Code:
    #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*.
     
  3. thread starter macrumors newbie

    Joined:
    Nov 8, 2010
    #3
    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?
     
  4. macrumors 65816

    Joined:
    Sep 19, 2009
    #4
    Hint: when posting code, using the code tags makes your code a lot easier to read. :)

    Code:
    #include <stdio.h>
    
    int main
    {
        printf( "Hello World!\n" );
        
        return 0;
    }
     
  5. cazador7907, Dec 1, 2010
    Last edited: Dec 1, 2010

    thread starter macrumors newbie

    Joined:
    Nov 8, 2010
    #5
    This is so FRUSTRATING!!

    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!!

    Code:
    //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;
    	[COLOR="Red"]newTFoo.PrintTFoo();   <---- THIS IS WHERE THE ERROR IS REPORTED[/COLOR]
    	
    }
     
  6. macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #6
    What happens when you remove '#include "main.h"'?
     
  7. thread starter macrumors newbie

    Joined:
    Nov 8, 2010
    #7
    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.
     
  8. macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #8
    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.

    Code:
    //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();
    	
    }
    
     
  9. macrumors 603

    Joined:
    Aug 9, 2009
    #9
    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.
     
  10. macrumors 6502a

    Joined:
    Jun 27, 2010
    #10
    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.
     
  11. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #11
    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.
     
  12. macrumors newbie

    Joined:
    Nov 30, 2010
    #12
    Code:
    //TFoo.h
    
    #include <iostream>
    
    template<typename T>
    class TFoo
    {
    public:
    	
    	void PrintTFoo();
    };
    [B][COLOR="Red"]#include "TFoo.cpp"[/COLOR][/B]
    
    //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;
    	[COLOR="Red"]newTFoo.PrintTFoo();   <---- THIS IS WHERE THE ERROR IS REPORTED[/COLOR]
    	
    }
    [/QUOTE]
     
  13. macrumors 68000

    Joined:
    Sep 10, 2008
    Location:
    Asheville, NC
    #13
    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.
     
  14. macrumors newbie

    Joined:
    Nov 30, 2010
    #14
    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/
     
  15. macrumors newbie

    Joined:
    Nov 30, 2010
    #15
    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.
     

Share This Page