I have the below class (which is basically a wrapper for std::vector), and one of the functions returns a variable of the type AInteger (which is basically a wrapper for int). Now the type AInteger is used multiple times throughout the class, yet the compiler starts complaining at a very specific position. When I remove the "getSize()" function, everything compiles just fine.
1>------ Build started: Project: ALibrary, Configuration: Debug Win32 ------
1> ASocket.cpp
1>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
1> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
1> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
1> AInteger.cpp
1>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
1> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
1> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
1> AHttpRequest.cpp
1>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
1> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
1> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
1> ABoolean.cpp
1>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
1> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
1> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
1> Generating Code...
1> Compiling...
1> AString.cpp
1> Generating Code...
2>------ Build started: Project: BitHoarder, Configuration: Debug Win32 ------
2> SystemHandler.cpp
2>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
2> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
2> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
2> Main.cpp
2>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
2> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
2> d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
2> Generating Code...
========== Build: 0 succeeded, 2 failed, 0 up-to-date, 0 skipped ==========
If any more code is needed just ask and I will provide.
dont declare it and replace the return type by VALUE the compiler will instantiate the class itself. if you wish to instanciate explicitly the template class then move your implementation in a cpp file and add at the end of the cpp file :
That's the thing though, only that function should return an AInteger. The template should be independent of that, so VALUE could be anything.
I've already figured out that the class will compile and run just fine if I replace AInteger getSize() const with AInteger & getSize() const although I'm not sure why, since that would simply create a variable which would go out of scope once the function is done.
Maybe it has something to do with template classes not being actual classes?
The point is that if you declare that the function returns an object of type AInteger then the compiler needs to know the complete definition of AInteger. Forward declaration won't cut it; you need the definition, so you need to actually include AInteger.h, or whatever header file contains that definition.
If you're just declaring the return value as a reference, then the compiler doesn't need to know the definition of AInteger, so forward declaration works. However...
[...] that would simply create a variable which would go out of scope once the function is done.
Well, no, not quite... you're creating a reference to a variable that has gone out of scope. But, yes, it's will lead to undefined behaviour, which is not what you want.
But when you say definition of AInteger, you mean the functions containing the actual code right? Because those are in a .cpp file which I can't include. I've already included the header for AInteger ("AInteger.h") but that only contains the declarations.
How come this doesn't work in template classes, but if I do the exact same thing in non-template classes it works fine? Is it because template classes contain inline definitions?
But when you say definition of AInteger, you mean the functions containing the actual code right? Because those are in a .cpp file which I can't include. I've already included the header for AInteger ("AInteger.h") but that only contains the declarations.
The class definition doesn't have to contain the definitions of the methods. When using a class (rather than just a reference to the class), the compiler needs to know things like the interface definition, and the size of the object. This means it needs to have the declarations of all the contents of the class, i.e. the stuff that needs to be in the class definition in the header file).
It doesn't need the definitions of the methods; those are resolved at link-time, and can be in another cpp file.
How come this doesn't work in template classes, but if I do the exact same thing in non-template classes it works fine? Is it because template classes contain inline definitions?
For templates, the compiler creates the entire class at compile-time, at the point where an object is created from the class template. This means that the entire definition of the class and its functions need to be available to the compiler.
It's one of the reasons I hate using templates, but modern design patterns rely heavily on them.
Oh, and the reason your test1.h doesn't work is because you're still using forward declaration for AInteger.
So I need to have the definition of the AInteger class inside the template class. I thought #include "AInteger.h" was supposed to take care of that? Since AInteger.h contains the definition of AInteger. Is there a reason the compiler is ignoring #include "AInteger.h" completely?
I've tried removing the forward declaration "class AInteger;" but it only leads to more errors.
I appreciate the effort, I really do, but that's not what I meant. By doing AList<AInteger> you're defining VALUE to be of the type AInteger. That's not my goal. AInteger is not the VALUE of the AList, it is just the return type of one of its functions. So for example, if I declare an AList like this: AList<std::string> list; the function getSize() should still return something of the type AInteger. This is because getSize() should always return the amount of items in the list. If in your code the list were to be declared as AList<std::string>, getSize() would return something which would be a type of std::string, which doesn't make any sense. So no matter what VALUE is, getSize() should return something of the type AInteger (which is a wrapper class I wrote for the default type int).
That is, of course, unless I'm missing something.
> So I need to have the definition of the AInteger class inside the template class.
We can (probably should) make AInteger a dependant name so that its look up is postponed to the point of actual instantiation (phase two of the two-phase lookup). We can then postpone the definition of AInteger till we actually use it. http://www.cplusplus.com/forum/beginner/103508/#msg557627
Why double template? The OP wants that method to always return the same type, regardless of what type the class is templated on. Why on earth would you make that return type templated?
Thanks Ericool, the errors saying that AInteger is undefined have now disappeared. But, in their place came a whole lot of new linker errors, all "unresolved external symbol". They're all very cryptic and don't give me any clue at all on how to solve them. They all point to line 1 of the AList.h file.
If it is needed I could possibly upload the project somewhere so someone could take a look. This problem has been bugging me for a week now :(
EDIT: I'm also receiving this error:
AList.obj : warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library