taylor_venable |
06-02-2006 05:44 PM |
C++ Template For Generic Function - Is This Possible?
I'm trying to write something roughly equivalent to the get-from (>>) and put-to (<<) operators from the istream and ostream STL classes. My class, however, is really just a wrapper for an fstream; it bundles two fstream objects into one interface, providing both << and >> operators. So my problem is, I want to use operator<< to write whatever the argument is to an "input" instance variable, and operator>> to read from an "output" instance variable into the argument. In other words, I want to pass the call to the << and >> operators down to whatever stream they apply to. But it's not working like I expected, and I get linker errors saying that specific functions (for different-typed arguments) are not defined.
The code will probably illustrate it best. Here's the header file for my class, Text_IO:
Code:
#ifndef _TEXT_IO_HH
#define _TEXT_IO_HH
#include <fstream>
#include <sstream>
#include <string>
#include "taylor/string.hh"
class Text_IO {
public:
Text_IO(std::string* in, std::string* out);
Text_IO(const char* in, const char* out);
std::string getline();
template <typename DATA_TYPE> Text_IO* operator>>(DATA_TYPE& dest);
template <typename DATA_TYPE> Text_IO* operator<<(DATA_TYPE src);
std::string getSentence();
private:
std::ifstream* input;
std::ofstream* output;
const char* SENTENCE_DELIM;
const char* WORD_DELIM;
};
#endif
And here's the actual implementation:
Code:
#include "text_io.hh"
Text_IO :: Text_IO(std::string* in, std::string* out) : SENTENCE_DELIM(".;:?!"), WORD_DELIM(" \t\r\n") {
this->input = new std::ifstream(in->c_str());
this->output = new std::ofstream(out->c_str());
}
Text_IO :: Text_IO(const char* in, const char* out) : SENTENCE_DELIM(".;:?!"), WORD_DELIM(" \t\r\n") {
this->input = new std::ifstream(in);
this->output = new std::ofstream(out);
}
std::string Text_IO :: getline(void) {
std::ostringstream oss;
char c;
while ((c = this->input->get()) != std::char_traits<char>::eof() && \
taylor :: string :: is_member_of(c, "\n")) oss << c;
return oss.str();
}
template <typename DATA_TYPE>
Text_IO* Text_IO :: operator>>(DATA_TYPE& dest) {
input >> dest;
return this;
}
template <typename DATA_TYPE>
Text_IO* Text_IO :: operator<<(DATA_TYPE data) {
this->output << data;
return this;
}
std::string Text_IO :: getSentence(void) {
std::ostringstream oss;
char c;
while ((c = this->input->get()) != std::char_traits<char>::eof() && \
taylor :: string :: is_member_of(c, SENTENCE_DELIM));
while ((c = this->input->get()) != std::char_traits<char>::eof() && \
! taylor :: string :: is_member_of(c, SENTENCE_DELIM)) oss << c;
return oss.str();
}
Lastly, here's my testing code:
Code:
#include <iostream>
#include "text_io.hh"
int main(int argc, char** argv) {
Text_IO file_io("input.txt", "output.txt");
std::string s;
s = file_io.getline();
std::cerr << "Read line from file: " << s << std::endl;
int i;
file_io >> i;
std::cerr << "Read integer from file: " << i << std::endl;
file_io << i;
file_io << "w00t!\n";
return 0;
}
And finally, here's the compilation command:
Code:
$ gmake text_io_test
g++ -g -Wall -Wabi -ansi -pedantic -o text_io_test text_io.o text_io_test.cc taylor/string.o
/var/tmp//ccQ993Ei.o(.text+0x1d4): In function `main':
/home/taylor/programs/testing/text_io_test.cc:21: undefined reference to `Text_IO* Text_IO::operator>><int>(int&)'
/var/tmp//ccQ993Ei.o(.text+0x21b):/home/taylor/programs/testing/text_io_test.cc:23: undefined reference to `Text_IO* Text_IO::operator<< <int>(int)'
/var/tmp//ccQ993Ei.o(.text+0x22f):/home/taylor/programs/testing/text_io_test.cc:24: undefined reference to `Text_IO* Text_IO::operator<< <char const*>(char const*)'
gmake: *** [text_io_test] Error 1
I thought that what I was trying to do was possible in C++, but maybe I was wrong. Do you have to define the function differently for every single type? Or can you use a template to automatically discern what type is being used in the call? Maybe it's just a syntax mistake on my part. Whatever the case, thanks in advance for any advice; this problem's had me stumped all day.
|