Technique 1 -> Results in error
I have three files MyType.h, MyType.cpp & main.cpp
MyType.h
#ifndef MYTYPE_H
#define MYTYPE_H
#include<iostream>
using namespace std;
template <class T,int iMax>
class A{
T iData;
public:
void vSetData(T iPar1);
void vDisplayData();
};
#endif
MyType.cpp
#include"MyType.h"
void A::vSetData(T iPar1){
if(iPar1 <= iMax)
iData = iPar1;
}
void A::vDisplayData(){
cout<<"\nData is: "<<iData<<endl;
}
main.cpp
#include"MyType.h"
typedef A<int,20> MyType;
int main(){
int x = 12;
MyType obj;
obj.vSetData(12);
obj.vDisplayData();
return 0;
}
ERRORS: 10 errors. They are as follows:-
mytype.cpp(2) : error C2955: 'A' : use of class template requires template argument list
mytype.h(9) : see declaration of 'A'
mytype.cpp(2) : error C2955: 'A' : use of class template requires template argument list
mytype.h(9) : see declaration of 'A'
mytype.cpp(2) : error C2065: 'T' : undeclared identifier
mytype.cpp(2) : error C2146: syntax error : missing ')' before identifier 'iPar1'
mytype.cpp(2) : error C2761: 'void A::vSetData(T)' : member function redeclaration not allowed
mytype.cpp(2) : error C2059: syntax error : ')'
mytype.cpp(2) : error C2143: syntax error : missing ';' before '{'
mytype.cpp(2) : error C2447: '{' : missing function header (old-style formal list?)
mytype.cpp(6) : error C2955: 'A' : use of class template requires template argument list
mytype.h(9) : see declaration of 'A'
mytype.cpp(6) : error C2509: 'vDisplayData' : member function not declared in 'A'
mytype.h(9) : see declaration of 'A
Technique 2 -> Works fine.
AboveCodeInOneFile.cpp
#include<iostream>
using namespace std;
template <class T,int iMax>
class A{
T iData;
public:
void vSetData(T iPar1){
if(iPar1 <= iMax)
iData = iPar1;
}
void vDisplayData(){
cout<<"\nData is: "<<iData<<endl;
}
};
typedef A<int,20> MyType;
int main(){
int x = 12;
MyType obj;
obj.vSetData(12);
obj.vDisplayData();
return 0;
}
Please let me know what mistake i am doing in Technique 1
When defining a template class, the method definition must be seen by the compiler. So they have to be in the header file.
Edit
You have to include the method implementation, so it's seen by the compiler. You can do it by including them from another `MyType_impl.h" file:
template <class T, int iMax>
void A<T, iMax>::vDisplayData()
{
cout<<"\nData is: "<<iData<<endl;
}
Each method definition needs the full class name decoration above it:
template <typename T>
void A<T>::vSetData(T iPar1){
if(iPar1 <= iMax)
iData = iPar1;
}
template <typename T>
void A<T>::vDisplayData(){
cout<<"\nData is: "<<iData<<endl;
}
When you do this however you'll get other compile errors, for the reasons Abhineet outlined. To fix this, you could put the definitions I wrote into the header file, beneath the class declaration, or you could put it in another header (MyType_Inc.h) and include /that/ header in the class declaration header
Technique 1 is wrong for templates. Don't use it.
Think of templates as blueprints for actual functions. Blueprints by themselves are not compilable. Only when you substitute template arguments (<class T,int iMax>) the actual functions are built. Because of this the compiler must see the blueprints when it tries to build functions from templates. In order to see the blueprints they must reside completely in header files.
When you define the member functions, you have to repeat the template parameters
template <class T,int iMax>
void A<T, iMax>::vSetData(T iPar1)
{
if(iPar1 <= iMax)
iData = iPar1;
}
That saves you from the compile errors.
The next problem is that templates defined in a .cpp file can only be used in that file. If you want to use them somewhere else, you really should put the definitions in the header.
There are two problems with your first version.
When implementing a member of a class template outside the class, you need to declare it as a template:
template <class T,int iMax>
void A<T,iMax>::vSetData(T iPar1){
if(iPar1 <= iMax)
iData = iPar1;
}
Also, the function definitions need to be available in any compilation unit that instantiates the template. In practice, this means you should usually define them inline (either inside the class template definition, or outside it but in a header file and declared inline). Simply defining them in a source file like you do will cause link errors.
Related
I have a templated class:
template <typename vtype>
class BNode
{
public:
BNode::BNode(std::vector<BPoly<vtype>>& thePolys) {if(thePolys.size()) Build(thePolys);}
BNode::BNode() {}
BPlane* mPlane=nullptr;
//And more stuff
};
When I compile, I get this error on the BPlane* mPlane=nullptr line:
error C2146: syntax error: missing ';' before identifier 'BPlane'
(Using Visual Studio 2019 compiler)
Why do I need a semicolon after my {}? If I put the semicolon there, it works. But I'm curious what the problem is because I'm worried there's some issue that will bite me later.
The following code compile without any error:
#include <vector>
class BPlane;
template <class T> class BPoly { int i; };
template <typename vtype>
class BNode
{
public:
BNode(std::vector<BPoly<vtype>> &thePolys) { if (thePolys.size()) Build(thePolys); }
BNode() {}
BPlane *mPlane = nullptr;
void Build(...) {}
//And more stuff
};
int main()
{
BNode<char> s;
}
Thus, it is impossible to guess what you have done wrong as after writing simple types for missing declaration and including vector the code compile without adding any ; after a constructor.
And I have made an instantiation in main to be sure that the class is used.
I have just started with C++ Qt and I wrote the following .h file: The .cpp file contains only empty constructors and destructors.
#include <QList>
class XML_Files
{
public:
XML_Files();
~XML_Files();
protected:
QList<Myclass> m_Xmls;
};
class Myclass
{
public:
Myclass();
~Myclass();
protected:
int a;
};
but I keep getting the following errors:
error C2065: 'Myclass': undeclared identifier
error C2923: 'QList': 'Myclass' is not a valid template type argument for parameter 'T'
What do I have to do to declare a Qlist with my own data type?
You can't use the name MyClass until the compiler knows about it. Since you do not declare MyClass until after XML_Files you cannot use it's name in XML_Files.
The simplest solution here is to just change the order of the declarations and declare MyClass before XML_Files.
The easy way to fix this, is to turn the order of both classes. However there is a second solution, if this is not desired or possible:
You may declare Myclass before defining it. Then compilation will succeed.
#include <QList>
class Myclass;
class XML_Files
{
public:
XML_Files();
~XML_Files();
protected:
QList<Myclass> m_Xmls;
};
class Myclass
{
// ...
};
I am trying to compile some code in mingw32 on windows XP and I got an error. So, I have write a simplified version of that code and got same error.
Here it is:
template <class T>
class Table
{
public:
class A
{
private:
int nEntry;
friend class B;
};
class B : public A
{
public:
void Remove()
{
nEntry = 1;
}
};
};
Compiler error message:
E:\cbProjects\projects\1\main.cpp||In member function 'void Table<T>::B::Remove()':|
E:\cbProjects\projects\1\main.cpp|24|error: 'nEntry' was not declared in this scope|
||=== Build finished: 1 errors, 0 warnings ===|
Where I can read the items why it's so? (links will be usefull - it may be happen that some other similar errors or compiler bags can appear)
Within a template, member access must sometimes be preceded by an explicit this->, as in this case. You can make your code work this way:
this->nEntry = 1;
I'm attempting to integrate googlemock into my tests. I had already successfully built and run tests on googletest, and now am trying to incrementally add the gmock functionality into the tests as well, but I've hit a compile error that I utterly do not understand.
I am not attempting to use or define mocked classes, or use anything gmock.h provides. At the top of my (previously working) tests.cpp file I merely type
#include "gmock/gmock.h"
And I get the compile error:
gmock/gmock-matchers.h(2497) : error C2059: syntax error : 'sizeof'
gmock/gmock-matchers.h(2505) : see reference to class template
instantiation 'testing::internal::ElementsAreMatcherImpl'
being compiled
gmock/gmock-matchers.h(2497) : error C2059: syntax error : ')'
gmock/gmock-matchers.h(2497) : error C2143: syntax error : missing ')'
before '{'
gmock/gmock-matchers.h(2497) : error C4430: missing type specifier -
int assumed. Note: C++ does not support default-int
gmock/gmock-matchers.h(2499) : warning C4183: 'Message': missing
return type; assumed to be a member function returning 'int'
I'm compiling this using nmake/vc++ on Windows 7, and I can't fathom why I would get these compile errors simply from adding the core gmock include file to my test file. Has anyone seen this sort of thing before?
Did you init google mock with InitGoogleMock(&__argc, __argv) in test project's main function?
You should include only "gmock/gmock.h" in your test files (and where you call InitGoogleMock) - no need for inclusion of gtest.h.
Have you updated your googletest library to googlemock. (https://github.com/google/googletest)
If all the things above are true it should work.
#include <iostream>
#include "gmock/gmock.h"
template <typename T>
class Foo : private T {
public:
void foo() {
T::bar();
}
};
class Bar {
public:
void bar() {
std::cout << "Hey there!" << std::endl;
}
};
int main() {
Foo<Bar> f;
f.foo();
}
template <typename T>
class Foo : private T {
public:
void foo() {
T::bar();
}
};
class Bar {
public:
void bar() {
std::cout << "Hey there!" << std::endl;
}
};
int main() {
Foo<Bar> f;
f.foo();
}
I am trying to implement a leftist tree using heaps as a base class. The following is the contents of heap.h:
template <class T>
class heap {
public:
virtual void init(T*) = 0;
virtual void insert(T*) = 0;
virtual T delete_min() = 0;
};
The following is the contents of leftist.cpp:
#include "heap.h"
template <class T>
class leftist_tree : public heap<T> {
private:
T* root;
public:
void init(T* a) {}
void insert(T* a) {}
T delete_min() {T a; return a;}
};
I am passing another class leftist_node as a parameter to this class using the following definition:
leftist_tree<leftist_node> mytree;
I am getting an LNK 2001 unresolved external symbol error for functions init, insert and delete_min. What am I doing wrong?
Edit:
Okay the example I have given at this point is far too complex. I have tried to reproduce the same error on a smaller scale so that someone can identify the problem more easily. I have created the following sample files.
try.cpp
#include "stdafx.h"
#include "myclass.h"
int _tmain(int argc, _TCHAR* argv[])
{
myclass<int> a;
a.hello(3);
return 0;
}
myclass.h
template <class T>
class myclass {
public:
void hello(T);
};
myclass.cpp
#include "myclass.h"
#include <iostream>
using namespace std;
template <class T>
void myclass<T>::hello(T a){
cout<<a<<endl;
system("pause");
}
I get a similar error message:
1>try.obj : error LNK2001: unresolved external symbol "public: void __thiscall myclass::hello(int)" (?hello#?$myclass#H##QAEXH#Z)
1>c:\users\meher anand\documents\visual studio 2010\Projects\try\Debug\try.exe : fatal error LNK1120: 1 unresolved externals
Can you tell me where I am going wrong right now? Thanks
Template functions are treated a little differently from regular functions. The compiler doesn't actually compile the function until you try to use it. If the only place you try to use it is a .cpp where the body of the function is undefined, it assumes it must be compiled somewhere else and makes a reference for the linker to fill in later.
In your case you defined the body of the functions in leftist.cpp, but you didn't use it there, you used it somewhere else. If you had defined it in the .h file then the definition would have been available everywhere you tried to use it and all would be well. If you had used the functions somewhere in leftist.cpp then the functions would have been created and the linker would have fixed everything up.
The general rule is to define the body of all template functions in the header files.
The template isn't instantiated for the type. The easiest way is to remove the .cpp from being compiled, and include it into the cpp where you use the template.
Another easy answer is to just define the whole template in the .h.
Whenever you see this error
error LNK20XX unresolved external symbol
It means that while linking the linker is unable to find the function definition. In your case it is error
Hope this helps you.
Let me know if you need any more help
PK
The following should work (tested with g++):
// File: heap.hh --------------------------
template <class T>
class heap {
public:a
virtual void init(T*) = 0;
virtual void insert(T*) = 0;
virtual T delete_min() = 0;
};
// File: leftist_tree.hh ------------------
#include "heap.hh"
template <class T>
class leftist_tree : public heap<T> {
private:
T* root;
public:
void init(T* ) {}
void insert(T* ) {}
T delete_min() {T a; return a;}
};
// File: leftist_node.hh ------------------
struct leftist_node {
int value;
};
// File: leftist_main.cpp -----------------
#include "leftist_tree.hh"
#include "leftist_node.hh"
int main() {
leftist_tree< leftist_node > mytree;
}