I have a rather standard situation where I want to use a templated class in the following way:
Define a .h file
Have it include the .cpp
In every other compiler that I try (i.e. g++ and clang/llvm) this works fine. In visual studio, it tells me that the file has already been defined.
If I manually cut and paste the text from the .cpp into the .h file, then everything works out just fine. I was under the impression that that was exactly what #include was supposed to do.
My hunch is that visual studio is compiling the .cpp file more than once somehow (though I placed #pragma once on the .h and .cpp files).
What is going on, and how can I make my template classes behave in VS?
Code follows:
.h:
#pragma once
template <class T>
class myVector
{
private:
void grow();
public:
int size;
int index;
T** words;
void pushBack(T* data);
inline T* operator[](int);
myVector(void);
~myVector(void);
};
#include "myVector.cpp"
.cpp:
#pragma once
#include "stdafx.h"
#include <cstdlib>
#include "myVector.h"
#include <iostream>
using namespace std;
template<class T>
myVector<T>::myVector(void)
{
this->size = 2000;
words = new T*[size];
index=0;
}
template<class T>
void myVector<T>::pushBack(T* input)
{
if(index<size)
{
words[index]=input;
}
else
{
grow();
words[index]=input;
}
index++;
}
template<class T>
T* myVector<T>::operator[](int i)
{
return words[i];
}
template<class T>
void myVector<T>::grow()
{
//cout<<"I grew:"<<endl;
size*=2;
words = (T**)realloc(words,size*sizeof(T*));
}
template<class T>
myVector<T>::~myVector(void)
{
delete[] words;
}
It seems to me that your confusion arises from not knowing how #pragma once and translation units work.
#pragma once, much like include guards, prevent the contents of a file (usually a header) from being pulled into a single translation unit more than once.
If you #include <vector> in multiple implementation files, the contents will be pulled in all of them, but only once for each translation unit.
So you should remove the #include "myVector.cpp", as MSVS automatically compiles implementation files, and it's also wrong.
Note that template definitions have to be visible, so you'll need to either move them to the .h file, like you did, or, using your current approach, rename the .cpp file to something like .impl or even .h and include it.
Related
I am trying to define a member struct of a class in a separate file. however, I not sure what is the correct way to implement it.
Below is what I have tried. in code1.cpp is the main source code. I would like to put the definition of the member struct, Mid, to a separate file, code2.cpp. However, in order for code2.cpp know the struct is part of TestCls, I import code1.cpp there and added the guards. I know this is not going to work but I am not sure how to make it work. Thanks
code1.cpp:
#include <iostream>
#include "code2.cpp"
class TestCls {
public:
struct Mid;
};
int main() {
TestCls::Mid mid1;
std::cout << mid1.a << std::endl;
}
code2.cpp
#ifndef XXX
#define XXX
#include <iostream>
#include <sys/dtrace.h>
#include "code1.cpp"
struct TestCls::Mid {
int a = 0;
};
#endif //XXX
Don't include cpp files. Only include header files. While headers files can technically have any (or no) suffix, using source file suffix may end up confusing a build system or compiler to think that it is supposed to be compiled, which you don't want to do with a header. .h or .hpp and few others are commonly used suffixes for headers.
Your code2.cpp includes code1.cpp and code1.cpp includes code2.cpp. Don't have recursive includes like this. While the include guard prevents infinite recursion, this can easily break in some cases.
For a small program like this, as an exercise, I recommend that you first write it entirely into a single file. For example, following would be correct:
class TestCls {
public:
struct Mid;
};
struct TestCls::Mid {
int a = 0;
};
#include <iostream>
int main() {
TestCls::Mid mid1;
std::cout << mid1.a << std::endl;
}
Now, you can slice the file into multiple ones while keeping the order.
// TestCls.hpp
#pragma once
class TestCls {
public:
struct Mid;
};
// TestClsMid.hpp
#pragma once
#include "TestCls.hpp"
struct TestCls::Mid {
int a = 0;
};
// main.cpp
#include "TestCls.hpp"
#include "TestClsMid.hpp"
#include <iostream>
int main() {
TestCls::Mid mid1;
std::cout << mid1.a << std::endl;
}
I used #pragma once for simplicity, buy you can opt for macro guards if you so prefer.
That said, I recommend to reconsider whehter there is any advantage in not defining TestCls::Mid in TestCls.hpp.
Here is the code for the question:
PlainInterface.h
/** PlainInterface.h */
#ifndef _PLAIN_INTERFACE
#define _PLAIN_INTERFACE
#include <vector>
template <class ItemType>
class PlainInterface{
public:
virtual int getSize () const = 0;
};
#endif
Plain.h
/** Plain.h */
#ifndef _PLAIN
#define _PLAIN
#include "PlainInterface.h";
template <class ItemType>
class Plain: public PlainInterface < ItemType > {
private:
std::vector<ItemType> a;
public:
Plain();
~Plain();
int getSize() const;
};
#include "Plain.cpp"
#endif
Plain.cpp
/* Plain.cpp */
#include <iostream>
#include "Plain.h"
//Constructors
template <class ItemType>
Plain<ItemType>::Plain() {
std::cout << "Created\n";
}
template <class ItemType>
Plain<ItemType>::~Plain() {
std::cout << "Destroyed\n";
}
template <class ItemType>
int Plain<ItemType>::getSize() const { return 0; }
So according to this question it said that you can either have all of the implementation in the header file, or put #include "Plain.cpp" at the end of the "Plain.h" file, or put the explicit instantiations at the end of the "Plain.cpp" file. I would like to keep the files seperate and not limit what is allowed into the templates. I tried the second option and it didn't work.
The errors that I am getting are that the constructor/deconstructor/getSize definitions in Plain.cpp are already defined. What am I doing wrong here?
You should remove #include "Plain.h" in your .cpp file, as you are creating a circular include otherwise.
Example:
//a.h
...
#include "b.cpp"
//b.cpp
#include "a.h"
a will include b, b will include a, and so on. This is probably why the second option you mentioned didn't work.
Here another answer that applies to your problem (I think): https://stackoverflow.com/a/3127374/2065501
I will not dare to ask why I need to add .cpp at end of .h while template declaration. Because it has been answered many times in StackOverflow.
But my question is, how come it is not circular dependency, or how compiler do not keep on adding .cpp into .h and .h into .cpp, when I add .cpp at end of header?
Does C++ 11 tries to solve this strange template requirement?
#Edit: Just including header file
#ifndef MYMAP
#define MYMAP
#include <iostream>
#include <string>
using namespace std;
template<typename ValType>
class MyMap
{
public:
MyMap();
~MyMap();
void add(string key, ValType val);
ValType getValue(string key);
private:
static const int NumBuckets = 99;
struct cellT
{
string key;
ValType val;
cellT* next;
};
cellT *buckets[NumBuckets];
int hash(string key, int numBuckets);
cellT* findCellForKey(string key, cellT *head);
MyMap(MyMap&);
MyMap operator = (MyMap&);
};
#include "MyMap.cpp" //included .cpp
#endif
#Edit 2 : MyMap.cpp
#include "MyMap.h"
//rest of the code
Thanks.
Leaving aside the merits of this technique, the code in your question works because of the include guard:
#ifndef MYMAP
#define MYMAP
...
#endif
The second time the .h is included, it is effectively a no-op since MYMAP has been defined the first time round.
P.S. Don't do using namespace std in a header file. Any code that includes this header will have the entire std namespace brought into the current scope irrespective of whether they want it or not.
I am implementing a simple Linked List, but I keep getting the LNK2019 error, I simplified my code to the minimum to track the problem,but I keep getting it. I am using Visual Studio 2010. My header file is:
#ifndef __TSLinkedList__H__
#define __TSLinkedList__H__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "LinkedNode.h"
template <class T>
class LinkedList
{
public:
LinkedList(void);
~LinkedList(void);
protected:
LinkedNode<T> * head;
};
The implementation file is:
#include "StdAfx.h"
#include "LinkedList.h"
template <class T>
LinkedList<T>::LinkedList(void)
{
head = NULL;
}
template <class T>
LinkedList<T>::~LinkedList(void)
{
}
the main function is:
#include "stdafx.h"
#include "stdlib.h"
#include "LinkedList.h"
int _tmain(int argc, _TCHAR* argv[])
{
LinkedList<int> mList;
system("PAUSE");
return 0;
}
and I am getting this error:
Error 1 error LNK2019: sÃmbolo externo "public: __thiscall LinkedList::~LinkedList(void)" (??1?$LinkedList#H##QAE#XZ) in function _wmain
I get the same error with the Constructor. The funny thing is that it is pointing to _wmain, and my main function is called _tmain. I already tried to change Subsystem linker from /SUBSYSTEM:WINODWS to /SUBSYSTEM:CONSOLE, but it was already set up as /SUBSYSTEM:CONSOLE. Obviously my implementation does a lot more than this, but I ripped out all of it to track this problem. Help wpuld be apreciated, this is driving me nuts. I am new to C++.
Move the function implementations to the header file.
In order to generate code for the specialization, the compiler must have the definitions of the functions available to each translation unit.
#ifndef __TSLinkedList__H__
#define __TSLinkedList__H__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "LinkedNode.h"
template <class T>
class LinkedList
{
public:
LinkedList(void);
~LinkedList(void);
protected:
LinkedNode<T> * head;
};
template <class T>
LinkedList<T>::LinkedList(void)
{
head = NULL;
}
template <class T>
LinkedList<T>::~LinkedList(void)
{
}
#endif
The compiler doesn't compile your template class member definitions, since they are not included in any compilation unit.
However, it does see that some members are used, so it will generate 'undefined' symbols for these.
Then comes the linker, trying to match the undefined symbols to some symbols defined in one of the compiled object files.
But, the LinkedList::~LinkedLis() destructor hasn't been compiled, so it's in none of the object files, and that's what the linker complains about.
You can fix this by
including the definition file in the main source file,
or pasting the definitions inside the template header file,
or including the template implementation file from the bottom of the template header file (my favorite)
I decided to cut the necessary code down to the bare minimum needed to display this error. I have an STL list wrapper template class that exists in hc_list.h file. The entire code is below:
// hc_list.h file
#ifndef HC_LIST_H
#define HC_LIST_H
#include <cstdlib>
#include <list>
template <typename T>
class hcList
{
private:
std::list<T> selfList ; // a single internal STL list to hold the values
public:
hcList(void) {} ;
~hcList(void){} ;
// The error occurs on the line below
template <typename U> friend std::ostream& operator<<(std::ostream &, const hcList<U> &) ;
} ;
#endif // HC_LIST_H
This code is included in the main.cpp file, where the main function is below:
// main.cpp file
#include <iostream>
#include "hc_list.h"
int main()
{
std::cout << "Begin Test" << std::endl;
return 0;
}
This code, when entered into a CodeBlocks project will compile as is with 0 errors or warnings. However, then I include another cpp file and attempt to include the list header, like the following:
// anyNamedFile.cpp file
#include "hc_list.h"
When I include any cpp file into the project, I get a compiler error:
error: expected initializer before '&' token
I do not understand what I am doing wrong, and could really use some help.
Your header file uses std::ostream, (just before an &) but does not include any header which might declare it.
Try adding
#include <iosfwd>
in your header.