473,320 Members | 2,162 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

linker errors with templates

Hello.

I can't understand why I can't compile the following simple code, where
I think I have applied all the needed rules for templates that are
declared and defined in different files (*.h and *.cpp).

What amazes me is that I have already some code like this in another
project where I don't get errors, so I am pretty sure I am missing some
stupid thing.

// file templates.h

#ifndef _TMPLT_
#define _TMPLT_

#include <iostream>

template <typename T>
class my_class;
template <typename T>
std::ostream& operator<<( std::ostream& out, const my_class<T>& obj );

template <typename T>
class my_class
{
public:
my_class( const T& v );
private:
friend std::ostream& operator<< <> (std::ostream& out,const
my_class<T>& obj);
const T val;
};

#endif

// file templates.cpp

#include "templates.h"

template class my_class<int>;

template <typename T>
my_class<T>::my_class( const T& v = T() )
: val( v )
{ }

template <typename T>
inline std::ostream& operator<<( std::ostream &out, const my_class<T>
&obj )
{
return out << obj.val << '\n';
}

// file main.cpp

#include "templates.h"

int main()
{
my_class<int> h1(99);
std::cout << h1;
return 0;
}

I compile it with gcc-3.4.1:

myself@myhost /temporary # g++ -c templates.cpp -o templates.o -Wall
myself@myhost /temporary # g++ main.cpp templates.o -Wall
/tmp/ccx0vMtF.o(.text+0x144): In function `main':
: undefined reference to `std::basic_ostream<char,
std::char_traits<char> >& operator<< <int>(std::basic_ostream<char,
std::char_traits<char> >&, my_class<int> const&)'
collect2: ld returned 1 exit status

Thanks in advance to everyone that points me to the errors in code.
Ciao,

Fabio De Francesco

Jul 22 '05 #1
12 1941
Fabio De Francesco wrote:
I can't understand why I can't compile the following simple code, where
I think I have applied all the needed rules for templates that are
declared and defined in different files (*.h and *.cpp).
[...]


This is covered in the FAQ. http://www.parashift.com/c++-faq-lite/

V
Jul 22 '05 #2
Maybe my post wasn't clear, due to my poor English...

I have already read the FAQ, this is the problem. What I said is that I
have some other similar code that is working by following the same
rules as the FAQ says.

Can you please have a closer look at the code?
Thank you,

Fabio De Francesco

Jul 22 '05 #3
Fabio De Francesco wrote:
Maybe my post wasn't clear, due to my poor English...

I have already read the FAQ, this is the problem. What I said is that I
have some other similar code that is working by following the same
rules as the FAQ says.


In most compilers today, you need to put the definition of a class
template's member functions in the class' definition, *not* in an
implementation file. Please, look closely at
http://www.parashift.com/c++-faq-lit...html#faq-34.13
and the following. And while you're at it, browse the whole FAQ.

If your code has already worked, it means the compiler you used was
probably able to implement the export keyword. Currently, afaik, only
Comeau does.
Jonathan
Jul 22 '05 #4
Fabio De Francesco wrote:
Maybe my post wasn't clear, due to my poor English...

I have already read the FAQ, this is the problem. What I said is that I
have some other similar code that is working by following the same
rules as the FAQ says.
You have _similar_ code working, but not this one. What specifically
makes the codes different? If you can't figure it out, how can we without
seeing the other code?
Can you please have a closer look at the code?


I have. You declare a function template 'operator<<'. You never give
the compiler a command to instantiate it (using explicit instantiation)
or give it the definition of the function when it is ready to produce
an implicit instantiation (while compiling 'main').

Either add an explicit instantiation or put the body in the header.

V
Jul 22 '05 #5
Thank you for your reply. But I am not able to understand yet.

What is meant by "explicit instantiation"?

Can you please show me where and how you would put it in my code?

The other code that I can compile with the same compiler and without
errors is the following one:

// file database.h

#ifndef _DATABASE_H_
#define _DATABASE_H_

#include <iostream>
#include <fstream>
#include <string>

using std::ostream;
using std::fstream;
using std::string;

template <typename T>
class DataBase;

template <typename T>
ostream& operator<<( ostream &out, DataBase<T> &db ); // friend
template functions must be forward declared

template <typename T>
class DataBase
{
public:
DataBase();
private:
fstream dataFile;
string fName;
void run();
void add( T & );
// functions skipped, not required for compiling
ostream& print( ostream & );
friend ostream& operator<< <> ( ostream &out, DataBase<T> &db );
// Note the unusual symbol <>
};

#endif
// file database.cpp

#include "person.h"
#include "database.h"

using std::ios;

template class DataBase<Person>;

template <typename T>
DataBase<T>::DataBase()
{
cin.clear();
while ( true )
{
cout << "\nEnter DataBase complete path: ";
if ( ( cin >> fName ) || ! cin.eof() )
{
if ( cin.good() )
this->run();
else
{
cin.clear();
cin.ignore(
std::numeric_limits<std::streamsize>::max(), '\n' );
cout << "\nBad input!";
}
}
else
{
cin.clear();
break;
}
}
}

template <typename T>
void DataBase<T>::run()
{

int option;
T record;
do
{
cout << "1. Add 2. Find 3. Modify 4. Exit\n";
if ( !( cin >> option ) || ( option < 1 ) || ( option > 4 ) )
{
cout << "Bad option!\n\n";
cin.clear();
cin.ignore( std::numeric_limits<std::streamsize>::max(),
'\n' );
continue;
}
switch ( option )
{
case 1:
cin >> record; // overloaded ">>"
add( record );
break;
// lot of code has been skipped, but it is possible to
compile without it
}
}
while ( option != 4 );
cout << "End of DataBase use\n\n";
cout.flush();
}

template <typename T>
void DataBase<T>::add( T &record )
{
dataFile.open( fName.c_str(), ios::out | ios::app );
dataFile.seekp(0,ios::end);
record.writeToFile(dataFile);
dataFile.close();
}

template <typename T>
inline ostream& operator<<( ostream &out, DataBase<T> &db )
{
return db.print( out );
}

// file usedb.cpp

#include "person.h"
#include "database.h"

int main()
{
DataBase<Person> dbPerson;
return 0;
}

The above copied code works and I am not able to see any difference
from the one that I posted at the thread start. I had to cut a lot of
code but what has been left can be compiled.

While wainting for your next reply, I thank you again.
Fabio De Francesco

Jul 22 '05 #6
Fabio De Francesco wrote:
Thank you for your reply. But I am not able to understand yet.

What is meant by "explicit instantiation"?
Doesn't the book you read to understand templates tell you about it?
Can you please show me where and how you would put it in my code?
You already have one. See below.
The other code that I can compile with the same compiler and without
errors is the following one:

// file database.h

#ifndef _DATABASE_H_
#define _DATABASE_H_

#include <iostream>
#include <fstream>
#include <string>

using std::ostream;
using std::fstream;
using std::string;

template <typename T>
class DataBase;

template <typename T>
ostream& operator<<( ostream &out, DataBase<T> &db ); // friend
template functions must be forward declared

template <typename T>
class DataBase
{
public:
DataBase();
private:
fstream dataFile;
string fName;
void run();
void add( T & );
// functions skipped, not required for compiling
ostream& print( ostream & );
friend ostream& operator<< <> ( ostream &out, DataBase<T> &db );
// Note the unusual symbol <>
};

#endif
// file database.cpp

#include "person.h"
#include "database.h"

using std::ios;

template class DataBase<Person>; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is an explicit instantiation.

template <typename T>
DataBase<T>::DataBase()
{
cin.clear();
while ( true )
{
cout << "\nEnter DataBase complete path: ";
if ( ( cin >> fName ) || ! cin.eof() )
{
if ( cin.good() )
this->run();
else
{
cin.clear();
cin.ignore(
std::numeric_limits<std::streamsize>::max(), '\n' );
cout << "\nBad input!";
}
}
else
{
cin.clear();
break;
}
}
}

template <typename T>
void DataBase<T>::run()
{

int option;
T record;
do
{
cout << "1. Add 2. Find 3. Modify 4. Exit\n";
if ( !( cin >> option ) || ( option < 1 ) || ( option > 4 ) )
{
cout << "Bad option!\n\n";
cin.clear();
cin.ignore( std::numeric_limits<std::streamsize>::max(),
'\n' );
continue;
}
switch ( option )
{
case 1:
cin >> record; // overloaded ">>"
add( record );
break;
// lot of code has been skipped, but it is possible to
compile without it
}
}
while ( option != 4 );
cout << "End of DataBase use\n\n";
cout.flush();
}

template <typename T>
void DataBase<T>::add( T &record )
{
dataFile.open( fName.c_str(), ios::out | ios::app );
dataFile.seekp(0,ios::end);
record.writeToFile(dataFile);
dataFile.close();
}

template <typename T>
inline ostream& operator<<( ostream &out, DataBase<T> &db )
{
return db.print( out );
}

// file usedb.cpp

#include "person.h"
#include "database.h"

int main()
{
DataBase<Person> dbPerson;
Yes, but in this file you don't make any attempt to use the operator<<.
And if you did, it wouldn't compile either.
return 0;
}

The above copied code works and I am not able to see any difference
from the one that I posted at the thread start.
Too bad.
I had to cut a lot of
code but what has been left can be compiled.


That's commendable. Posting minimal code that still does what you say is
what is usually needed for this newsgroup.

V
Jul 22 '05 #7
Right in that FAQ is explained how to avoid those linker errors. And I
think I am following their suggestions that don't require to put the
definition of a class template's member function in the class
definition inside the .h file.
Please read the document from "The solution is to convince the compiler
while it is examining the class body proper ..."
Ciao,

Fabio De Francesco

Jul 22 '05 #8
Fabio De Francesco wrote:
Right in that FAQ is explained how to avoid those linker errors. And I
think I am following their suggestions that don't require to put the
definition of a class template's member function in the class
definition inside the .h file.
That only resolves the linker errors regarding the class members. If you
have other templates, like functions, like your operator<<, for example,
wouldn't it be logical to extend the suggestion and put the definition of
those/that function into the header too?
Please read the document from "The solution is to convince the compiler
while it is examining the class body proper ..."


But your compiler is complaining about a non-member function, isn't it?

V
Jul 22 '05 #9
Ah, now I understand the issue.

I have been confused about the meaning of "explicit instantiation"
because I supposed that the line "template class my_class<int>;" was
the only "explicit instantiation" the program needed.

After your last reply I tried to include a similar explicit
instantiation also for the friend function like the following:

template std::ostream& operator<<( std::ostream& out, const
my_class<int>& obj );

and that made the program to compile and to work.

I didn't imagine to be required to add that line because it is not
required for other functions in the class. Maybe I am too lazy... but I
don't see where this is showed in the FAQ (at section 34.15). What I
see there is only the class explicit instantiation, but here is about
midnight.

If you have a look at section 34.14 you can see another omission, that
is when the author writes the explicit instantiation of a class it
writes only "template Foo<int>;" instead of "template class Foo<int>;".
Do you think is it correct? My compiler doesn't work without the
"class" in it.

Thank you again,

Fabio De Francesco

Jul 22 '05 #10
Fabio De Francesco wrote:
Ah, now I understand the issue.

I have been confused about the meaning of "explicit instantiation"
because I supposed that the line "template class my_class<int>;" was
the only "explicit instantiation" the program needed.

After your last reply I tried to include a similar explicit
instantiation also for the friend function like the following:

template std::ostream& operator<<( std::ostream& out, const
my_class<int>& obj );

and that made the program to compile and to work.
Good.
I didn't imagine to be required to add that line because it is not
required for other functions in the class. Maybe I am too lazy...
The 'operator <<' is not a "function in the class", is it?
but I
don't see where this is showed in the FAQ (at section 34.15). What I
see there is only the class explicit instantiation, but here is about
midnight.

If you have a look at section 34.14 you can see another omission, that
is when the author writes the explicit instantiation of a class it
writes only "template Foo<int>;" instead of "template class Foo<int>;".
Do you think is it correct? My compiler doesn't work without the
"class" in it.


You should bring both issues to the attention of Marshall Cline, the
maintainer of the FAQ. The link to his e-mail is on the front page of
the FAQ.

V
Jul 22 '05 #11

Victor Bazarov wrote:
Fabio De Francesco wrote:
Ah, now I understand the issue.

I have been confused about the meaning of "explicit instantiation"
because I supposed that the line "template class my_class<int>;" was the only "explicit instantiation" the program needed.

After your last reply I tried to include a similar explicit
instantiation also for the friend function like the following:

template std::ostream& operator<<( std::ostream& out, const
my_class<int>& obj );

and that made the program to compile and to work.
Good.
I didn't imagine to be required to add that line because it is not
required for other functions in the class. Maybe I am too lazy...


The 'operator <<' is not a "function in the class", is it?
> but I
don't see where this is showed in the FAQ (at section 34.15). What I see there is only the class explicit instantiation, but here is about midnight.
>
If you have a look at section 34.14 you can see another omission, that is when the author writes the explicit instantiation of a class it
writes only "template Foo<int>;" instead of "template class Foo<int>;". Do you think is it correct? My compiler doesn't work without the
"class" in it.


You should bring both issues to the attention of Marshall Cline, the
maintainer of the FAQ. The link to his e-mail is on the front page

of the FAQ.

V


If you agree with my observations about those FAQ's sections, please
would you bring those issues to the attention of Mr. Cline? I don't
write a good enough English at a level I think it is required for
commenting on the document and proposing changes. Furthermore I don't
have enough knowledge of the C++ language required by that task.

So, please would you (or someone else with the same knoledge of the
issues)do it?

Thank you,

Fabio De Francesco

Jul 22 '05 #12
Fabio De Francesco wrote:
[...]
If you agree with my observations about those FAQ's sections,
Actually, I don't. Just look at 34.13. But if you still feel that
you have some suggestions how to improve the FAQ, please address
Marshall yourself.
please
would you bring those issues to the attention of Mr. Cline? I don't
write a good enough English at a level I think it is required for
commenting on the document and proposing changes. Furthermore I don't
have enough knowledge of the C++ language required by that task.
If you feel you know enough English to argue with me about who should
e-mail Marshall, then you know enough English to e-mail him yourself.

As to the knowledge of C++, the only thing that matters is _his_ C++
level, which is sufficient. If there is an error or omission in the FAQ,
it will be corrected, and if there isn't, you will be told.
So, please would you (or someone else with the same knoledge of the
issues)do it?


If you won't do it, it won't be done.

V
Jul 22 '05 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: william xuuu | last post by:
Actually, I also got linker errors with template functions and template classes. And I avoided both of them successfully, by pouring foo.cpp into foo.h, according to the C++ FAQ. ...
1
by: Generic Usenet Account | last post by:
I am "plugging in" a class type into an STL map definition and I am getting linker errors unless all my class definitions are defined in the header file, as opposed to a separate source file. This...
1
by: Rebecca Hoffmann | last post by:
Hi, I have a serious problem while compiling a small project (a part of the Modular Flow Scheduling Middleware: ex1): There are 3 linker errors, all from symbols that point to templates: --...
3
by: Grahamo | last post by:
Hi, I have a question that pertains to Templates and link time. This is totally for my own understanding and to correct what's obviously an erroneous view of things on my behalf; Lets say I...
4
by: PyongHopscotch | last post by:
Hi All, So I'm getting the generic linker error (unresolved external error) in VC 7.0 when I define a templatized function. Here's some code examples: template <class T> class...
2
by: Robbie Hatley | last post by:
"Victor Bazarov" <v.Abazarov@comAcast.net> wrote: > Robbie Hatley wrote: > > > > I ran into a problem a few days ago when I added a couple of > > template functions to one of my personal...
1
by: toton | last post by:
In C++ , when the class is declared in the header & not implemented in the cpp, the linker is not giving a error untill the method gets called. How to ensure that all non pure-virtual method...
5
by: Mark | last post by:
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...
2
by: Markus Dehmann | last post by:
What to do if an external library is header-files-only (but you have to use it), and you get lots of linker errors? You will necessarily get linker errors "multiple definition of ..." if you try...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.