Help | Site Map
Connecting Tech Pros Worldwide
 
 
LinkBack Thread Tools
  #1  
Old November 10th, 2006, 06:55 AM
Mark
Guest
 
Posts: n/a
Default linker error w/ templates

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<intv1;

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[i] = r.m_pElements[i];
}

// 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?

  #2  
Old November 10th, 2006, 07:05 AM
Jacek Dziedzic
Guest
 
Posts: n/a
Default Re: linker error w/ templates

Mark wrote:
Quote:
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<intv1;
>
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[i] = r.m_pElements[i];
}
>
// 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.
  #3  
Old November 10th, 2006, 07:45 AM
Mark
Guest
 
Posts: n/a
Default Re: linker error w/ templates


Jacek Dziedzic wrote:
Quote:
Mark wrote:
Quote:
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<intv1;

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[i] = r.m_pElements[i];
}

// 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.

  #4  
Old November 10th, 2006, 08:05 AM
Salt_Peter
Guest
 
Posts: n/a
Default Re: linker error w/ templates


Mark wrote:
Quote:
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 <stdexcept>
Quote:
using namespace std;
loose the using directive
Quote:
>
int main(int argc, char *argv[])
{
Vector<intv1;
>
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;
}
Quote:
>
// Vector.h
>
#ifndef VECTOR_H
#define VECTOR_H
#include <stdexcept>
Quote:
>
class IndexOutofBounds {
};
>
template <class T>
class Vector {
public:
Vector();
Vector(int size);
Vector(size_t size); // suggestion
Quote:
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?
Quote:
int size();
size_t size() const;
Quote:
int inflate(int addSize);
size_t infalte(const size_t addSize);
Quote:
private:
T *m_pElements;
int m_nSize;
size_t m_nSize;
Quote:
};
Note: size_t is just a suggestion. The const are not.
Quote:
>
#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?
Quote:
>
template <class T>
Vector<T>::Vector() : m_nSize(0), m_pElements(0) {}
nice
Quote:
>
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.
Quote:
}
>
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[i] = r.m_pElements[i];
}
>
// 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.

  #5  
Old November 18th, 2006, 09:15 AM
Mark
Guest
 
Posts: n/a
Default Re: linker error w/ templates


Salt_Peter wrote:
Quote:
Mark wrote:
Quote:
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 <stdexcept>
Quote:
using namespace std;
>
loose the using directive
>
Quote:

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

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;
}
>
Quote:

// Vector.h

#ifndef VECTOR_H
#define VECTOR_H
>
#include <stdexcept>
>
Quote:

class IndexOutofBounds {
};

template <class T>
class Vector {
public:
Vector();
Vector(int size);
>
Vector(size_t size); // suggestion
>
Quote:
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?
>
Quote:
int size();
>
size_t size() const;
>
Quote:
int inflate(int addSize);
size_t infalte(const size_t addSize);
Quote:
private:
T *m_pElements;
int m_nSize;
>
size_t m_nSize;
>
Quote:
};
>
Note: size_t is just a suggestion. The const are not.
>
Quote:

#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?
>
Quote:

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

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.
>
Quote:
}

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[i] = r.m_pElements[i];
}

// 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

  #6  
Old November 21st, 2006, 01:25 AM
BobR
Guest
 
Posts: n/a
Default Re: linker error w/ templates


Mark wrote in message ...
Quote:
>
>couldn't I have just added a catch( ... ) instead of adding this
>bad_exception?
Salt_Peter told you:
Quote:
Quote:
>>
>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.
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.
Quote:
>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.

--
Bob R
POVrookie


 

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over network members.
Post your question now . . .
It's fast and it's free

Popular Articles