views:

205

answers:

6

The compiler says it can't find the reference for the function when I do this:

// link.h
template <class T>
    T *Link(T *&, T *(*)())

// link.cpp
template <class T>
T c:Link(T *&ChildNodeReference, T *(*ObjectCreator)()){

}

If I implement inside the class on the header it goes smoothly.

Please, I will work on the header until someone enlightens me about this.

There are somethings in C++ that are weirdly annoying. I know, there is a reason for this and etc. Even so, can't the compilers help you out about it -_-"

+4  A: 

Templated implementations (not only definitions) have to be available at compile time.

So, the full template code is normally put in the header file.

gnud
aren't my .cpp units being compiled as well?why normal functions are ok and not the templated ones?is there anyway to not have to put my hard work obvious to others?
Jonathan
Template classes and functions are only compiled when they are used, so the code inside the functions must be present for the compiler to be able to instantiate specific types.
Nick Bedford
so why do we have the .cpp files?we should all programm at the header file, because we can't split the classes for better and organized public libraries and we can't code templated classes at the unit... this looks like c# more each time I try new stuff.
Jonathan
Here's the world's tiniest violin: #=={=}
1800 INFORMATION
Templates are the exception, Jonathan.Templates in C++ work fundamentally different from C#/Java Generics. Have a look at http://blogs.msdn.com/csharpfaq/archive/2004/03/12/88913.aspx
gnud
A: 

Template code must be in the header. Sorry, I completely missed that! (and I thought I'd been coding C++ for years :P)

Nick Bedford
there is no other way?seriously, why does someone bother to create .cpp units if you can't just use itseriously, I had so much expectations of freedom in coding and C++ is letting me down...
Jonathan
Templates are the only part of C++ which require this (other than inline functions). CPP units are heavily utilised everywhere else. A header is just code placed into source file which is then compiled. There's nothing special about cpp files. Templates must be provided with full source otherwise the compiler has no function code to compile. its just the way C++ works.
Nick Bedford
A: 

You forgot the * for the return type. So implementation is not matching definition. Add it and it should work:

T *c:Link(T *&ChildNodeReference, T *(*ObjectCreator)())
{
}

Implementation must be too in the header file under the class definition in order to be available at compile time.

Patrice Bernassola
+1  A: 

Programming non-template code or non-inlined functions in headers is a Bad Thing™. The reason you have cpp files is to prevent redefinition of the same function code more than once, amongst other things.

The difference with templates is that the compiler practically doesn't touch them until your code instantiates a specialisation of that template which is why they need to have their source inside the header.

When the compiler finds an instantiation of a template specialisation (say List<int>), it goes back to the included template code and compiles it with that specialisation, which is why you don't have issues with redefinition of function code.

What you don't seem to understand is that this doesn't apply to non-templated code. All non-template code is compiled as normal and thus CPP files are needed to only define the code once then link it all together.

If you define functions inside a header, your linker will not link the compiled translation units because they have defined the same function more than once.

Nick Bedford
Of course, one can just mark all non-template functions inline as well, and also ditch the .cpp...
Pavel Minaev
A: 

Good.

Thanks guys, I understood it.

I won't use templates.

the organization I wanted isn't worth the problematic and performance of templates, from what I've seen here and there.

Jonathan
You'll be hard pressed to write a generic sorting non-template function that would match the performance of a corresponding function template. This may or may not be an issue, but templates _are_ part of idiomatic C++, and if you ignore them, you're essentially ignoring a very large part of the language (and also standard library - are you going to avoid `std::vector<T>` as well, for example?), and, frankly, at that point there's little reason to even bother with C++...
Pavel Minaev
no, I will use std::vector, in fact I am already. But I won't use it for my own classes because I didn't see anything good on templates if not lists.I was only trying to skip some static_casts, but it does not worth it so far.and templates aren't C++ main stuff, in my point of view, C++ is about classes and inheritance... OOP in general. But I am still designing the project, so I can change it without problems... Ty for your comment.
Jonathan
A: 

Templates are essentially semi-type-safe macros, hence the limitation.

Normal (non-template) functions can be compiled to native code residing object/library files, and then referenced with only a prototype available in the header, solely because there's only a single version of such a function.

With templates, C++ compiler has to compile each instantiation of the function separately. Obviously, it cannot do it "in advance", because the set of types for which you can instantiate the function is effectively unbounded (you can always define a new type in your code before calling the function). In fact, two instantiations of the same function template can be completely different. Consider this extreme case:

struct t1 {
  template <int>
  struct a {};
};

struct t2 {
  enum { a = 123 }; 
};

enum { b = 456, c = 789 };

template <class T>
void foo() {
   T::a<b>c;
}

Now if we call foo<t1>(), the statement inside it is a local variable declaration, because t1::a is a class template:

T::a<b> c;

But if we call foo<t2>(), the statement inside is an expression, because t2::a is an integral constant:

(T::a < b) > c;

This is just to show that compiler cannot meaningfully "compile" a template; it really has to mostly preserve the tokens.

Now, all that said, ISO C++ does actually provide the ability to separate declaration and definition of templates, so that they can be treated as normal functions, with declarations in .h files, and definitions in .cpp files. This is called "export templates", because you have to precede both declaration and definiton with keyword export:

// link.h
export template <class T>
T *Link(T *&, T *(*)());

// link.cpp
export template <class T>
T *Link(T *&ChildNodeReference, T *(*ObjectCreator)()) {
}

This is, however, a controversial feature of the Standard because of very high burden on implementation, and most popular implementations refuse to implement it; notably, g++, MSVC, and C++Builder do not implement it. The only compiler I know of that supports it is Comeau C++.

Pavel Minaev
The problem is simplified if the types to be used in a template are known a priori. For example, if a function is a template for int, char and float numbers, one can declare the template function with these types in the header file and define the template in the cpp file. See http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13