linker error w/ templates

M

Mark

Sorry for creating such a newbish topic, but I just can't seem to
figure out what the problem is here.

// main.cpp

#include <cstdlib>
#include <iostream>
#include "Vector.h"
using namespace std;

int main(int argc, char *argv[])
{
Vector<int> v1;

system("PAUSE");
return EXIT_SUCCESS;
}

// Vector.h

#ifndef VECTOR_H
#define VECTOR_H

class IndexOutofBounds {
};

template <class T>
class Vector {
public:
Vector();
Vector(int size);
Vector(const Vector& r);// COPY
virtual ~Vector();
T& operator[](int index) throw(IndexOutofBounds);
int size();
int inflate(int addSize);
private:
T *m_pElements;
int m_nSize;
};

#endif

// Vector.cpp

#include "Vector.h"

// consturctors

template <class T>
Vector<T>::Vector() : m_nSize(0), m_pElements(0) {}

template <class T>
Vector<T>::Vector(int size) : m_nSize(size) {
m_pElements = new T[m_nSize];
}

template <class T>
Vector<T>::Vector(const Vector& r) {
m_nSize = r.m_nSize;
m_pElements = new T[m_nSize];
for(int i=0; i<m_nSize; i++)
m_pElements = r.m_pElements;
}

// destructor

template <class T>
Vector<T>::~Vector() {
delete[] m_pElements;

// ... plus rest of functions

compile log:

g++.exe -c main.cpp -o main.o
-I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"
-I"C:/Dev-Cpp/include/c++/3.4.2/backward"
-I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"
-I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

g++.exe -c Vector.cpp -o Vector.o
-I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"
-I"C:/Dev-Cpp/include/c++/3.4.2/backward"
-I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"
-I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

g++.exe main.o Vector.o -o "Project1.exe" -L"C:/Dev-Cpp/lib"

main.o(.text+0x16a):main.cpp: undefined reference to
`Vector<int>::Vector()'
main.o(.text+0x175):main.cpp: undefined reference to
`Vector<int>::~Vector()'
collect2: ld returned 1 exit status

make.exe: *** [Project1.exe] Error 1

Execution terminated


I don't understand why I'm getting the linker error... Vector.cpp is
compiled, everything *should* be defined, no?
 
J

Jacek Dziedzic

Mark said:
Sorry for creating such a newbish topic, but I just can't seem to
figure out what the problem is here.

// main.cpp

#include <cstdlib>
#include <iostream>
#include "Vector.h"
using namespace std;

int main(int argc, char *argv[])
{
Vector<int> v1;

system("PAUSE");
return EXIT_SUCCESS;
}

// Vector.h

#ifndef VECTOR_H
#define VECTOR_H

class IndexOutofBounds {
};

template <class T>
class Vector {
public:
Vector();
Vector(int size);
Vector(const Vector& r);// COPY
virtual ~Vector();
T& operator[](int index) throw(IndexOutofBounds);
int size();
int inflate(int addSize);
private:
T *m_pElements;
int m_nSize;
};

#endif

// Vector.cpp

#include "Vector.h"

// consturctors

template <class T>
Vector<T>::Vector() : m_nSize(0), m_pElements(0) {}

template <class T>
Vector<T>::Vector(int size) : m_nSize(size) {
m_pElements = new T[m_nSize];
}

template <class T>
Vector<T>::Vector(const Vector& r) {
m_nSize = r.m_nSize;
m_pElements = new T[m_nSize];
for(int i=0; i<m_nSize; i++)
m_pElements = r.m_pElements;
}

// destructor

template <class T>
Vector<T>::~Vector() {
delete[] m_pElements;

// ... plus rest of functions

compile log:

g++.exe -c main.cpp -o main.o
-I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"
-I"C:/Dev-Cpp/include/c++/3.4.2/backward"
-I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"
-I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

g++.exe -c Vector.cpp -o Vector.o
-I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"
-I"C:/Dev-Cpp/include/c++/3.4.2/backward"
-I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"
-I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

g++.exe main.o Vector.o -o "Project1.exe" -L"C:/Dev-Cpp/lib"

main.o(.text+0x16a):main.cpp: undefined reference to
`Vector<int>::Vector()'
main.o(.text+0x175):main.cpp: undefined reference to
`Vector<int>::~Vector()'
collect2: ld returned 1 exit status

make.exe: *** [Project1.exe] Error 1

Execution terminated


I don't understand why I'm getting the linker error... Vector.cpp is
compiled, everything *should* be defined, no?


No. In main.cpp your definition of Vector's constructor and
destructor must be visible. It is because it is in main.cpp
where the template is _instantiated_. Therefore, you will have
to move the definitions to the header file. This sounds weird,
but is what one ususally does with templates -- writing all
the code within the .h file so that it's visible whenever this
header file is included.

HTH,
- J.
 
M

Mark

Jacek said:
Mark said:
Sorry for creating such a newbish topic, but I just can't seem to
figure out what the problem is here.

// main.cpp

#include <cstdlib>
#include <iostream>
#include "Vector.h"
using namespace std;

int main(int argc, char *argv[])
{
Vector<int> v1;

system("PAUSE");
return EXIT_SUCCESS;
}

// Vector.h

#ifndef VECTOR_H
#define VECTOR_H

class IndexOutofBounds {
};

template <class T>
class Vector {
public:
Vector();
Vector(int size);
Vector(const Vector& r);// COPY
virtual ~Vector();
T& operator[](int index) throw(IndexOutofBounds);
int size();
int inflate(int addSize);
private:
T *m_pElements;
int m_nSize;
};

#endif

// Vector.cpp

#include "Vector.h"

// consturctors

template <class T>
Vector<T>::Vector() : m_nSize(0), m_pElements(0) {}

template <class T>
Vector<T>::Vector(int size) : m_nSize(size) {
m_pElements = new T[m_nSize];
}

template <class T>
Vector<T>::Vector(const Vector& r) {
m_nSize = r.m_nSize;
m_pElements = new T[m_nSize];
for(int i=0; i<m_nSize; i++)
m_pElements = r.m_pElements;
}

// destructor

template <class T>
Vector<T>::~Vector() {
delete[] m_pElements;

// ... plus rest of functions

compile log:

g++.exe -c main.cpp -o main.o
-I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"
-I"C:/Dev-Cpp/include/c++/3.4.2/backward"
-I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"
-I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

g++.exe -c Vector.cpp -o Vector.o
-I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"
-I"C:/Dev-Cpp/include/c++/3.4.2/backward"
-I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"
-I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

g++.exe main.o Vector.o -o "Project1.exe" -L"C:/Dev-Cpp/lib"

main.o(.text+0x16a):main.cpp: undefined reference to
`Vector<int>::Vector()'
main.o(.text+0x175):main.cpp: undefined reference to
`Vector<int>::~Vector()'
collect2: ld returned 1 exit status

make.exe: *** [Project1.exe] Error 1

Execution terminated


I don't understand why I'm getting the linker error... Vector.cpp is
compiled, everything *should* be defined, no?


No. In main.cpp your definition of Vector's constructor and
destructor must be visible. It is because it is in main.cpp
where the template is _instantiated_. Therefore, you will have
to move the definitions to the header file. This sounds weird,
but is what one ususally does with templates -- writing all
the code within the .h file so that it's visible whenever this
header file is included.

HTH,
- J.


Hrm... that's kind of strange. But it solves the problem! Thank you
so much.
 
S

Salt_Peter

Mark said:
Sorry for creating such a newbish topic, but I just can't seem to
figure out what the problem is here.

// main.cpp

#include <cstdlib>
#include <iostream>
#include "Vector.h"
#include said:
using namespace std;

loose the using directive
int main(int argc, char *argv[])
{
Vector<int> v1;

system("PAUSE");
return EXIT_SUCCESS;
}

int main()
{
try
{
Vector< int > vn;
// throw std::runtime_error("testing runtime_error");
}
catch( const IndexOutofBounds& r_e )
{
std::cout << "error: index out of bounds caught!\n";
}
catch ( const std::exception& r_e )
{
std::cout << "error: ";
std::cout << r_e.what() << std::endl;
}
return 0;
}
// Vector.h

#ifndef VECTOR_H
#define VECTOR_H

#include said:
class IndexOutofBounds {
};

template <class T>
class Vector {
public:
Vector();
Vector(int size);

Vector(size_t size); // suggestion
Vector(const Vector& r);// COPY
virtual ~Vector();
T& operator[](int index) throw(IndexOutofBounds);

T& operator[](size_t index)
throw(IndexOutofBounds, std::bad_exception);

See below about the bad_exception...
assignment operator?
int size();

size_t size() const;
int inflate(int addSize);
size_t infalte(const size_t addSize);
private:
T *m_pElements;
int m_nSize;

size_t m_nSize;

Note: size_t is just a suggestion. The const are not.
#endif

// Vector.cpp

#include "Vector.h"

// consturctors

Keep your templates inline or read the faq:
http://www.parashift.com/c++-faq-lite/templates.html
[35.15] How can I avoid linker errors with my template classes?
template <class T>
Vector<T>::Vector() : m_nSize(0), m_pElements(0) {}
nice


template <class T>
Vector<T>::Vector(int size) : m_nSize(size) {
m_pElements = new T[m_nSize];

consider smart pointers, like boost::shared_ptr.
Highly recommended and easy to use.
}

template <class T>
Vector<T>::Vector(const Vector& r) {
m_nSize = r.m_nSize;
m_pElements = new T[m_nSize];
for(int i=0; i<m_nSize; i++)
m_pElements = r.m_pElements;
}

// destructor

template <class T>
Vector<T>::~Vector() {
delete[] m_pElements;

// ... plus rest of functions

compile log:

g++.exe -c main.cpp -o main.o
-I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"
-I"C:/Dev-Cpp/include/c++/3.4.2/backward"
-I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"
-I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

g++.exe -c Vector.cpp -o Vector.o
-I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"
-I"C:/Dev-Cpp/include/c++/3.4.2/backward"
-I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"
-I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

g++.exe main.o Vector.o -o "Project1.exe" -L"C:/Dev-Cpp/lib"

main.o(.text+0x16a):main.cpp: undefined reference to
`Vector<int>::Vector()'
main.o(.text+0x175):main.cpp: undefined reference to
`Vector<int>::~Vector()'
collect2: ld returned 1 exit status

make.exe: *** [Project1.exe] Error 1

Execution terminated


I don't understand why I'm getting the linker error... Vector.cpp is
compiled, everything *should* be defined, no?


Read the faq 35.15

Now, you need to catch exceptions if you are going to use them.
So i added the try-catch blocks in main.
The reason i'm adding std::bad_exception to your exception
specification in op[] is:

_If_ an exception *other* than IndexOutofBounds gets thrown from
operator[], unexpected() calls terminate() immediately. Why? because
the exception specification was *violated*.

If bad_exception is part of that function's exception specification,
then unexpected() rethrows a bad_exception. Which is nice to know cause
you'll see that in main's catch(const std::exception&) block.

Its up to you if you feel that you can do without bad_exception in your
except spec.
 
M

Mark

Salt_Peter said:
Mark said:
Sorry for creating such a newbish topic, but I just can't seem to
figure out what the problem is here.

// main.cpp

#include <cstdlib>
#include <iostream>
#include "Vector.h"
#include said:
using namespace std;

loose the using directive
int main(int argc, char *argv[])
{
Vector<int> v1;

system("PAUSE");
return EXIT_SUCCESS;
}

int main()
{
try
{
Vector< int > vn;
// throw std::runtime_error("testing runtime_error");
}
catch( const IndexOutofBounds& r_e )
{
std::cout << "error: index out of bounds caught!\n";
}
catch ( const std::exception& r_e )
{
std::cout << "error: ";
std::cout << r_e.what() << std::endl;
}
return 0;
}
// Vector.h

#ifndef VECTOR_H
#define VECTOR_H

#include said:
class IndexOutofBounds {
};

template <class T>
class Vector {
public:
Vector();
Vector(int size);

Vector(size_t size); // suggestion
Vector(const Vector& r);// COPY
virtual ~Vector();
T& operator[](int index) throw(IndexOutofBounds);

T& operator[](size_t index)
throw(IndexOutofBounds, std::bad_exception);

See below about the bad_exception...
assignment operator?
int size();

size_t size() const;
int inflate(int addSize);
size_t infalte(const size_t addSize);
private:
T *m_pElements;
int m_nSize;

size_t m_nSize;

Note: size_t is just a suggestion. The const are not.
#endif

// Vector.cpp

#include "Vector.h"

// consturctors

Keep your templates inline or read the faq:
http://www.parashift.com/c++-faq-lite/templates.html
[35.15] How can I avoid linker errors with my template classes?
template <class T>
Vector<T>::Vector() : m_nSize(0), m_pElements(0) {}
nice


template <class T>
Vector<T>::Vector(int size) : m_nSize(size) {
m_pElements = new T[m_nSize];

consider smart pointers, like boost::shared_ptr.
Highly recommended and easy to use.
}

template <class T>
Vector<T>::Vector(const Vector& r) {
m_nSize = r.m_nSize;
m_pElements = new T[m_nSize];
for(int i=0; i<m_nSize; i++)
m_pElements = r.m_pElements;
}

// destructor

template <class T>
Vector<T>::~Vector() {
delete[] m_pElements;

// ... plus rest of functions

compile log:

g++.exe -c main.cpp -o main.o
-I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"
-I"C:/Dev-Cpp/include/c++/3.4.2/backward"
-I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"
-I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

g++.exe -c Vector.cpp -o Vector.o
-I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"
-I"C:/Dev-Cpp/include/c++/3.4.2/backward"
-I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"
-I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"

g++.exe main.o Vector.o -o "Project1.exe" -L"C:/Dev-Cpp/lib"

main.o(.text+0x16a):main.cpp: undefined reference to
`Vector<int>::Vector()'
main.o(.text+0x175):main.cpp: undefined reference to
`Vector<int>::~Vector()'
collect2: ld returned 1 exit status

make.exe: *** [Project1.exe] Error 1

Execution terminated


I don't understand why I'm getting the linker error... Vector.cpp is
compiled, everything *should* be defined, no?


Read the faq 35.15

Now, you need to catch exceptions if you are going to use them.
So i added the try-catch blocks in main.
The reason i'm adding std::bad_exception to your exception
specification in op[] is:

_If_ an exception *other* than IndexOutofBounds gets thrown from
operator[], unexpected() calls terminate() immediately. Why? because
the exception specification was *violated*.

If bad_exception is part of that function's exception specification,
then unexpected() rethrows a bad_exception. Which is nice to know cause
you'll see that in main's catch(const std::exception&) block.

Its up to you if you feel that you can do without bad_exception in your
except spec.


couldn't I have just added a catch( ... ) instead of adding this
bad_exception?
and I could have just added
template class Vector<int>;
to....what..main.cpp? instead of moving everything into the .h

thanks for the help
 
B

BobR

Mark wrote in message ...
couldn't I have just added a catch( ... ) instead of adding this
bad_exception?

Salt_Peter told you:
catch( ... )

.....is a "catch-all". You have no chance to see where it came from, or
'.what()' messages.

Above that catch (in the chain) is the 'unhandled exception' handler. Default
for it is to terminate. You can set it to your own handler.
and I could have just added
template class Vector<int>;
to....what..main.cpp? instead of moving everything into the .h

I don't see why not, just don't put it inside main(). <G>

If you put it in a header, it's easier to include in other projects in the
future.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Dev C++ compile problem 2
ld returned 1 exit status Error 1
templates?? 2
boost program_options link error 1
GDB, I know, I know, off topic 2
template error 10
Templates and g++ 4
Does not name a type error 1

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top