LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 06-02-2006, 05:44 PM   #1
taylor_venable
Member
 
Registered: Jun 2005
Location: Indiana, USA
Distribution: OpenBSD, Ubuntu
Posts: 892

Rep: Reputation: 40
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.
 
Old 06-04-2006, 02:47 AM   #2
spooon
Senior Member
 
Registered: Aug 2005
Posts: 1,755

Rep: Reputation: 48
I am not very familiar with C++ syntax, but I thought it was "template<class DATA_TYPE>"
 
Old 06-04-2006, 10:11 AM   #3
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147
If I remember correctly the definition and declaration of the member template need to be in the same header file. This is because the compiler will then expand the required functions.

I would also suggest that you first build it without using templates and once taht is working add the template feature (you may have done that in which case sorry for butting in )

Last edited by graemef; 06-04-2006 at 10:13 AM.
 
Old 06-04-2006, 10:15 AM   #4
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147
Quote:
Originally Posted by spooon
I am not very familiar with C++ syntax, but I thought it was "template<class DATA_TYPE>"
In C++ the use of class and typename in a template are interchangable and have the same meaning. Convention is, use class if it refers to a class otherwise use typename.
 
Old 06-05-2006, 11:33 AM   #5
taylor_venable
Member
 
Registered: Jun 2005
Location: Indiana, USA
Distribution: OpenBSD, Ubuntu
Posts: 892

Original Poster
Rep: Reputation: 40
Quote:
Originally Posted by graemef
If I remember correctly the definition and declaration of the member template need to be in the same header file. This is because the compiler will then expand the required functions.
Ah, thank you! It works beautifully now.

But I don't quite understand why it works. Doesn't the #include at the top of the implementation ensure that the header file is present before the implementation, in the same file? Or is it that when #include is activated, template expansion takes place in the header, and then (after the expansion) the file is included into the implementation file?
 
Old 06-05-2006, 11:54 AM   #6
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147
(I believe) It's because that header files are one way. That is the source code knows about the header file but the header file doesn't know about the source code. So unless the template code is in the header file the compiler is not able to expand it when it comes across a new implementation of the template.
 
Old 06-05-2006, 08:46 PM   #7
taylor_venable
Member
 
Registered: Jun 2005
Location: Indiana, USA
Distribution: OpenBSD, Ubuntu
Posts: 892

Original Poster
Rep: Reputation: 40
Hmm, OK; that sounds sensical. Thanks a bunch for the idea, that actually solved another problem I was having, as well. It's kind of crazy how flexible and powerful C++ can be when working with this sort of stuff.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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 On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
"undefined reference" to a template class function btb Programming 3 08-25-2005 05:02 PM
Template class with a template member... Nicholas Bishop Programming 3 02-21-2005 08:27 PM
When "function pointer" meets "template"... I can't get rid of this compiling er cyu021 Linux - Software 3 12-17-2004 07:52 PM
function prototypes in template class' (c++) qwijibow Programming 4 12-13-2004 09:34 AM
problem in template function. compiles in vc++ not in gcc 3.0.4 cybercop12us Programming 4 12-12-2002 01:04 AM


All times are GMT -5. The time now is 08:24 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration