Reputation: 1624
I need to generated a simple Logger (with out third party libs) that's need to be link to dll. Therefore I generated a class with some of his class method were templates, the code compile fine but I get linker error. I am compiling with MS VS 2008 and gcc-4. The code is:
Log.h class:
class MiniLogger
{
private:
std::ofstream mOutPutFile;
protected:
void write (std::string const& text);
public:
~MiniLogger();
MiniLogger( std::string const& lName) throw(FileError);
static MiniLogger* getInstance(std::string const & fName);
static void destoryInstance(MiniLogger*);
template<class T>
MiniLogger& operator<<(T & data);
MiniLogger& operator<<(std::ostream& (*func)(std::ostream&) );
};
MiniLogger& MiniLogger::operator<< (std::ostream& (*func)(std::ostream&))
{
//mOutPutFile << out;
return *this;
}
template<class T>
MiniLogger& MiniLogger::operator<< (T & data)
{
//Just try with out calling other method
// write(data);
return *this;
}
At main I instantiated the Object and use it :
#include "log.h"
int main()
{
MiniLogger &a=*(MiniLogger::getInstance("text.txt"));
a << "text" << std::endl;
return 0;
}
I get
@ubu11-10-64b-01:~/cplus/template$ g++ main.cpp log.cpp
/tmp/cccMdSBI.o: In function `MiniLogger::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))':
log.cpp:(.text+0x0): multiple definition of `MiniLogger::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))'
/tmp/ccj3dfhR.o:main.cpp:(.text+0x0): first defined here
Upvotes: 3
Views: 322
Reputation: 168876
You've defined a function in a header file. Since that header file is included in multiple translation units (namely, main.cpp and log.cpp), you've multiply defined the function. (See the One Definition Rule.)
Either declare the function inline
and define it in the header file, or declare it extern
in the header file and define in exactly one source file.
The function in question is: MiniLogger& MiniLogger::operator<< (std::ostream& (*func)(std::ostream&))
.
Solution #1:
// Log.h
inline
MiniLogger& MiniLogger::operator<< (std::ostream& (*func)(std::ostream&))
{
//mOutPutFile << out;
return *this;
}
Solution #2:
// Log.h
extern
MiniLogger& MiniLogger::operator<< (std::ostream& (*func)(std::ostream&));
// Log.cpp
MiniLogger& MiniLogger::operator<< (std::ostream& (*func)(std::ostream&))
{
//mOutPutFile << out;
return *this;
}
template<class T>
MiniLogger& MiniLogger::operator<< (T & data)
, is not a function – it is a function template – and different advice applies to it. As a rule of thumb, you should define function templates in header files, but should not define functions in header files. (There are exceptions to this rule of thumb.)
Upvotes: 4