When I compile this:
Code:
#include <iostream>
#include <ctime>
#include <cstring>
#include <string>
#include <fstream>
#include <sstream>
#define LGROPENFAIL 1
#define LGRWRITEFAIL 2
class logger {
public:
std::ofstream log;
logger(std::string fpath, std::string who, bool fatal, bool buffd);
template<typename T> logger& operator<< (const T &data);
void stamp();
~logger();
private:
std::string id;
bool fatal;
bool buffd;
};
logger::logger(std::string fpath, std::string who, bool fatal, bool buffd) {
log.open(fpath.c_str(), std::ios::app|std::ios::out);
this->fatal = fatal;
this->buffd = buffd;
if (log.rdstate() && fatal) throw LGROPENFAIL;
id = who;
stamp();
log << "LOGGER BEGIN.\n";
if (!buffd) log.flush();
}
template<typename T> logger& logger::operator<< (const T &data) {
std::stringstream oss;
oss << data;
log << oss.str();
if (!buffd) log.flush();
if (log.rdstate() && fatal) throw LGRWRITEFAIL;
return *this;
}
void logger::stamp() {
const time_t t = time(NULL);
char *ts = ctime(&t), *p = strrchr(ts,' ');
*(++p) = '\0';
log << ts << id << ": ";
if (log.rdstate() && fatal) throw LGRWRITEFAIL;
}
logger::~logger() {
stamp();
log << "LOGGER DONE.\n";
log.close();
}
using namespace std;
int main() {
logger log("test.log", "tester", true, true);
log.stamp();
log << "hey" << 23 << "\n";
return 0;
}
Everything works just fine. However, if I compile the class seperately:
logger.h
Code:
#include <ctime>
#include <cstring>
#include <string>
#include <fstream>
#include <sstream>
#ifndef LGROPENFAIL
#define LGROPENFAIL 1
#define LGRWRITEFAIL 2
#endif
class logger {
public:
std::ofstream log;
logger(std::string fpath, std::string who, bool fatal, bool buffd);
template<typename T> logger& operator<< (const T &data);
void stamp();
~logger();
private:
std::string id;
bool fatal;
bool buffd;
};
logger.cpp
Code:
#include <logger.h>
logger::logger(std::string fpath, std::string who, bool fatal, bool buffd) {
log.open(fpath.c_str(), std::ios::app|std::ios::out);
this->fatal = fatal;
this->buffd = buffd;
if (log.rdstate() && fatal) throw LGROPENFAIL;
id = who;
stamp();
log << "LOGGER BEGIN.\n";
if (!buffd) log.flush();
}
template<typename T> logger& logger::operator<< (const T &data) {
std::stringstream oss;
oss << data;
log << oss.str();
if (!buffd) log.flush();
if (log.rdstate() && fatal) throw LGRWRITEFAIL;
return *this;
}
void logger::stamp() {
const time_t t = time(NULL);
char *ts = ctime(&t), *p = strrchr(ts,' ');
*(++p) = '\0';
log << ts << id << ": ";
if (log.rdstate() && fatal) throw LGRWRITEFAIL;
}
logger::~logger() {
stamp();
log << "LOGGER DONE.\n";
log.close();
}
Compile:
g++ -c -o logger.o logger.cpp
ar rcs liblogger++.a logger.o
Then use this:
logger-demo.cpp
Code:
#include <logger.h>
using namespace std;
int main() {
logger log("test.log", "tester", true, true);
log.stamp();
log << "hey" << 23 << "\n";
return 0;
}
and compile:
gcc logger-demo.cpp -llogger++
I suddenly get:
/tmp/ccDZcs1z.o: In function `main':
logger-demo.cpp.text+0x24b): undefined reference to `logger& logger:perator<< <char [4]>(char const (&) [4])'
logger-demo.cpp.text+0x257): undefined reference to `logger& logger:perator<< <int>(int const&)'
logger-demo.cpp.text+0x264): undefined reference to `logger& logger:perator<< <char [2]>(char const (&) [2])'
collect2: ld returned 1 exit status
So this is all specifically to do with the one template func overloading <<. I've never had a problem creating a static lib in C before, and I can't find any distinct caveats regarding doing it in C++. Anyone know what the deal is? I'm hoping it's just a switch I can add..