There are quite a few posts like this on Stack Overflow, but most of them pertain to Xcode, and I cannot replicate their solutions. I have a Heap.h, Heap.cpp, and main.cpp file and whenever I try to run main.cpp with g++ main.cpp Heap.cpp, it gives me:
clang: error: linker command failed with exit code 1 (use -v to see invocation)
File Heap.h
#ifndef _HEAP_H_
#define _HEAP_H_
template<class T>
class Heap{
private:
struct Node{
T *dist;
T *v;
bool operator==(const Node& a){
return *dist == *(a -> dist);
}
bool operator!=(const Node& a){
return (!(*dist == *(a -> dist)));
}
};
Node *container;
int size;
int curSize;
T sourceV;
public:
Heap();
Heap(int inSize, T inSourceV);
};
#endif
File Heap.cpp
#include <iostream>
#include <vector>
#include <limits>
#include "Heap.h"
using namespace std;
template<class T>
Heap<T>::Heap(){
cout << "hello" <<endl;
}
template<class T>
Heap<T>::Heap(int inSize, T inSourceV){
size = inSize;
container = new Node[size];
curSize = 0;
sourceV = inSourceV;
int maxVal = numeric_limits<int>::max();
for (int i = 1; i < size; i++){
container[i].dist = &maxVal;
container[i].v = &maxVal;
}
}
File main.cpp
#include "Heap.h"
#include <iostream>
using namespace std;
int main(){
Heap <int> h;
}
It is strange I have another project that contains bst.h, bst.cpp, and main.cpp, and those run fine. The difference between these two projects is that the bst I implemented is not a templated class.
I also saw another similar post that mentioned something about changing bitcode settings, but where can I access that from?
I'm running Xcode 7.1. Apple LLVM version 7.0.0 (clang-700.1.76).
Target: x86_64-apple-darwin14.5.0
Thread model: posix
You don't instantiate a Heap<int> in the Heap.cpp compilation. As a result the compiler doesn't bother generating any code for Heap.o.
You can see this if you do:
nm Heap.o
It tells you there's nothing there.
This is a typical behaviour of a C++ compiler - no template gets turned into code unless there's an instantiation of it.
Quick solutions are
Move all the Heap.cpp code into the template class declaration of Heap.h
create a dummy function in Heap.cpp that instantiates a Heap<int>
Related
I'm working on a simple class List, but when compiling the header and cpp file, I get the error: undefined reference to `main'
What am I doing wrong, and how could I fix this?
Here is the list.h file that has simple headers:
list.h
#ifndef LIST_H
#define LIST_H
#include <string>
const int DEFAULT_CAPACITY = 100;
class List
{
public:
List();
List(int capacity);
~List();
void push_back(std::string s);
int size() const;
std::string at(int index) const;
private:
std::string* mData;
int mSize;
int mCapacity;
};
#endif
And here is the list.cpp file:
list.cpp
#include "list.h"
#include <string>
List::List(){
mData = new std::string[DEFAULT_CAPACITY];
mSize = 0;
mCapacity = 100;
};
List::List(int capacity){
mData = new std::string[capacity];
mSize = 0;
mCapacity = capacity;
};
List::~List(){
delete[] mData;
};
void List::push_back(std::string s){
if (mSize<mCapacity){
mData[mSize] = s;
mSize++;
}
};
int List::size() const{
return mSize;
};
std::string List::at(int index) const{
return mData[index];
};
I tried experimenting around with "using namespace std" and how to include , but I can't figure out how to get these errors to go away. What is causing them?
You should be able to compile list.cpp, you can't link it unless you have a main program. (That might be a slight oversimplification.)
The way to compile a source file without linking it depends on what compiler you're using. If you're using g++, the command would be:
g++ -c list.cpp
That will generate an object file containing the machine code for your class. Depending on your compiler and OS, it might be called list.o or list.obj.
If you instead try:
g++ list.cpp
it will assume that you've defined a main function and try to generate an executable, resulting in the error you've seen (because you haven't defined a main function).
At some point, of course, you'll need a program that uses your class. To do that, you'll need another .cpp source file that has a #include "list.h" and a main() function. You can compile that source file and link the resulting object together with the object generated from list.cpp to generate a working executable. With g++, you can do that in one step, for example:
g++ list.cpp main.cpp -o main
You have to have a main function somewhere. It doesn't necessarily have to be in list.cpp. And as a matter of style and code organization, it probably shouldn't be in list.cpp; you might want to be able to use that class from more than one main program.
Undefined reference to main() means that your program lacks a main() function, which is mandatory for all C++ programs. Add this somewhere:
int main()
{
return 0;
}
I have been stuck for a while now and am unable to figure out why I am getting this compile error.
Node.hpp
#ifndef H1
#define H1
template <typename T>
class Node{
private:
T data;
public:
T getData();
};
#endif
Node.cpp
#include "Node.hpp"
template<typename T>
T Node<T>::getData(){
return data;
}
main.cpp
#include <bits/stdc++.h>
#include "Node.hpp"
using namespace std;
int main()
{
Node<int> *n = new Node<int>();
cout << n->getData();
}
g++ main.cpp Node.cpp -std=c++17
O/P: main.cpp:(.text+0x24): undefined reference to `Node::getData()'collect2: error: ld returned 1 exit status
PS: I tried the same thing without any template (use a primitive datatype instead), I do not get any error. So this probably has got something to do with the typename. Would be great if someone could tell me what is wrong here.
Node.hpp
#ifndef H1
#define H1
template <typename T>
class Node{
private:
T data;
public:
T getData() { return data; }
};
//or define it here
#endif
Then no need for Node.cpp. You might want to consider returning a const reference if your use-case allows it as T now requires a copy constructor. Although maybe that's what you want, I don't know your use-case.
See Why can template only be defined in header files
I have a problem with the linking of a C++ project and I can't figure out what's wrong.
The jest of the code.
clitest.cpp
#include <iostream>
#include "node.h"
using namespace std;
int main(int argc, char** argv)
{
node<int> *ndNew = new node<int>(7);
return 0;
}
node.h
#ifndef NODE_H
#define NODE_H
#include <vector>
template <typename T>
class node
{
private:
node<T>* ndFather;
std::vector<node<T>* > vecSons;
public:
T* Data;
node(const T &Data);
};
#endif
node.cpp
#include "node.h"
using namespace std;
template <typename T>
node<T>::node(const T &Data)
{
this->Data = &Data;
this->ndFather = 0;
this->vecSons = (new vector<T>());
};
The compiler command that was used is
g++ -Wall -g clitest.cpp node.cpp -o clitest
The error log is goes like this
clitest.cpp: In function ‘int main(int, char**)’:
clitest.cpp:8:16: warning: unused variable ‘ndNew’ [-Wunused-variable]
node<int> *ndNew = new node<int>(7);
^
/tmp/cc258ryG.o: In function `main':
clitest.cpp:8: undefined reference to `node<int>::node(int const&)'
collect2: error: ld returned 1 exit status
make: *** [blist] Error 1
I have spent a decent amount of time shifting the code around, Trying to identify the problem and I either miss something basic, Or it's something I don't know about C++ linkage.
When using templates, the compiler needs to know how to generate the code for the class when it is instantiated. The undefined reference error is caused because the compiler did not generate the node<int>::node(int const &) constructor. See, e.g. Why can templates only be implemented in the header file?
You have a couple of options:
Put the implementation in node.h (node.cpp is removed as it not needed)
Put the implementation in a file that is #included at the bottom of node.h (usually the file would be called node.tpp)
I suggest putting the implementation in node.h and removing node.cpp. Note that the code in your example is not valid c++: the member variable vecSons is not a pointer so the line vecSons = new vector<T>() will give a compiler error. The following code could be a starting point for the full implementation:
#ifndef NODE_H
#define NODE_H
#include <vector>
template <typename T>
class node
{
private:
node<T>* ndFather;
std::vector<node<T>* > vecSons;
public:
const T* Data;
node(const T &d) :
ndFather(0),
vecSons(),
Data(&d)
{
}
};
#endif
Use -I. before the .cpp files, so that the compiler knows to look for .h files.
g++ -Wall -I. clitest.cpp node.cpp -o clitest
Or just -I:
g++ -Wall -I clitest.cpp node.cpp -o clitest
I'm working on a simple class List, but when compiling the header and cpp file, I get the error: undefined reference to `main'
What am I doing wrong, and how could I fix this?
Here is the list.h file that has simple headers:
list.h
#ifndef LIST_H
#define LIST_H
#include <string>
const int DEFAULT_CAPACITY = 100;
class List
{
public:
List();
List(int capacity);
~List();
void push_back(std::string s);
int size() const;
std::string at(int index) const;
private:
std::string* mData;
int mSize;
int mCapacity;
};
#endif
And here is the list.cpp file:
list.cpp
#include "list.h"
#include <string>
List::List(){
mData = new std::string[DEFAULT_CAPACITY];
mSize = 0;
mCapacity = 100;
};
List::List(int capacity){
mData = new std::string[capacity];
mSize = 0;
mCapacity = capacity;
};
List::~List(){
delete[] mData;
};
void List::push_back(std::string s){
if (mSize<mCapacity){
mData[mSize] = s;
mSize++;
}
};
int List::size() const{
return mSize;
};
std::string List::at(int index) const{
return mData[index];
};
I tried experimenting around with "using namespace std" and how to include , but I can't figure out how to get these errors to go away. What is causing them?
You should be able to compile list.cpp, you can't link it unless you have a main program. (That might be a slight oversimplification.)
The way to compile a source file without linking it depends on what compiler you're using. If you're using g++, the command would be:
g++ -c list.cpp
That will generate an object file containing the machine code for your class. Depending on your compiler and OS, it might be called list.o or list.obj.
If you instead try:
g++ list.cpp
it will assume that you've defined a main function and try to generate an executable, resulting in the error you've seen (because you haven't defined a main function).
At some point, of course, you'll need a program that uses your class. To do that, you'll need another .cpp source file that has a #include "list.h" and a main() function. You can compile that source file and link the resulting object together with the object generated from list.cpp to generate a working executable. With g++, you can do that in one step, for example:
g++ list.cpp main.cpp -o main
You have to have a main function somewhere. It doesn't necessarily have to be in list.cpp. And as a matter of style and code organization, it probably shouldn't be in list.cpp; you might want to be able to use that class from more than one main program.
Undefined reference to main() means that your program lacks a main() function, which is mandatory for all C++ programs. Add this somewhere:
int main()
{
return 0;
}
I'm trying to create a linked list class in Eclipse but I can't get it to compile properly.
Here is my .cc file (code snipet)
#include <iostream>
#include "list.h"
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
and here is my list.h file (code snipet)
#ifndef __LIST_H__
#define __LIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
#include "list.cc"
#endif /* __LIST_H__ */
I try "Building All" in eclipse but I get the following error:
make all
Building file: ../list.cc
Invoking: Cross G++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"list.d" -MT"list.d" -o "list.o" "../list.cc"
../list.cc:13: error: redefinition of 'bool List<T>::isEmpty()'
../list.cc:13: error: 'bool List<T>::isEmpty()' previously declared here
make: *** [list.o] Error 1
Help please...thanks. I'll be happy to provide any clarifications needed
EDIT: I was given the .h file so I know that it is correct. I also know that I am supposed to have a .cc file called list.cc (it is included at the end of the .h file)
You need to change the extension of the file with the implementation.
The compiler will process this file for compilation and will process it twice, since you're including it in the header.
Your file looks like this:
#include <iostream>
#include "list.h"
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
which will become
#include <iostream>
#ifndef __DLIST_H__
#define __DLIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
#include "dlist.cc"
#endif /* __DLIST_H__ */
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
which will in turn become
#include <iostream>
#ifndef __DLIST_H__
#define __DLIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
#endif /* __DLIST_H__ */
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
So the function isEmpty() is defined twice.
Rename the file to dlist.impl.
Try putting the definition for List<T>::isEmpty() in the same file as the class is declared.
Given the unusual form of the header you've been supplied with, to test it you will need another source file. To start with the new source file (say test.cpp) can just #include "list.h", which will check for any syntax errors but will not yet instantiate your List template.
(Just compile test.cpp, not list.cc, since list.cc is indirectly included by test.cpp)