I am trying to write an API (called logEvent) for an outdated os-level logging function. I would like to call it in the following manner.

logEvent << "string";
// or
logEvent << "string" << 123 << 0.456 << ... ;

I'm trying to accomplish this by overloading the stream operator, and making it take a template argument so it will pass it to the outdated logging function. I have tried befriending ostream, but I can't get it to work either way, nor do I really understand why I need to do that.

The way I have it right now, I get the following linker error, but only when I call the overloaded operator from main.cpp (below).

main.obj : error LNK2019: unresolved external symbol "public: class logEvent * __thiscall logEvent::operator<<<int>(int)" (??$?6H@logEvent@@QAEPAV0@H@Z) referenced in function _main

I have been up and down the web (including this forum) and have not been able to find a solution. Any help is greatly appreciated.

// main.cpp
#include "logEvent.h"

using namespace std;
int main()
{
    logEvent e;
    e << 123;

    return 0;
}
// logEvent.h
#include <string>
#include <sstream>

class logEvent
{
public:
    logEvent();

    template< typename T >
    logEvent *operator<<( T arg );
}
// logEvent.cpp
#include <string>
#include <sstream>

template< typename T >
logEvent *logEvent::operator<<( T arg )
{
    oldLog( arg );

    return this;
}

Return reference of logEvent object.

#include <string>
#include <sstream>

class logEvent
{
public:
    logEvent();

    template< typename T >
    logEvent &operator<<( T arg );
}
template< typename T >
logEvent &logEvent::operator<<( T arg )
{
    oldLog( arg );
    return *this;
}

Thanks for replying.

When I make the changes you gave me, I get a linker error:

main.obj : error LNK2019: unresolved external symbol "public: class logEvent & __thiscall logEvent::operator<<<int>(int)" (??$?6H@logEvent@@QAEAAV0@H@Z) referenced in function _main

I created a new project and put in exactly the code I posted in the OP, just to see if the problem was something extraneous, but no luck.

Please post your code. Linker error shows that you didn't implement such a method (post #3).

Please post your code. Linker error shows that you didn't implement such a method (post #3).

I'm hoping it's something stupid I'm over-looking. I'm using MS Visual Studio 2005 to compile, btw.

// main.cpp
#include <iostream>
#include "logEvent.h"

using namespace std;

int main()
{
    logEvent e;

    cout << "\n                   ***      LOGIC TEST FOR logEvent.cpp      ***\n" << endl;

    e << 123;

    return 0;
}
// logEvent.h
#ifndef LOGEVENT_H
#define LOGEVENT_H

#include <string>
#include <sstream>

class logEvent
{
public:
    logEvent();

    template< typename T >
    logEvent &operator<<( T arg );
};

#endif // LOGEVENT_H
// logEvent.cpp

#include "logEvent.h"

#include <string>
#include <sstream>

//#define TERMINAL_WINDOW_WIDTH   80

using namespace std;

logEvent::logEvent()
{
    
}

template< typename T >
logEvent &logEvent::operator<<( T arg )
{
    cout << arg << endl;
    return *this;
}

http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13 and thereabouts.

This is good information, and it offered three solutions:

  1. Move the template function definition into the .h file
  2. Include a function definition in the .cpp file
  3. Create a third file, such as logEvent-impl.cpp, containg only the following code:
    #include "logEvent.cpp"
     
    template logEvent &operator<<<T>( T arg );

None of these seemed to work. The errors I received, respectively, are as follows:

  1. 1>main.obj : error LNK2019: unresolved external symbol "public: class logEvent & __thiscall logEvent::operator<<<int>(int)" (??$?6H@logEvent@@QAEAAV0@H@Z) referenced in function _main
  2. I can't declare the function outside of the class definition, so the error message is irrelevant.
  3. 1>c:\documents and settings\usr\my documents\visual studio 2005\projects\logevent\logevent\logeventstreamop.cpp(1) : fatal error C1083: Cannot open include file: 'logEvent.cpp': No such file or directory (And I did remember to add the new file to the project.)

I read almost that entire page, and these were the only solutions it suggested. Defining a separate method for each instance will cause me to have to write three more methods for those methods, so I would REALLY like to be able to use a template here. Why, oh, why can't we just use Java here?

The first suggestion worked dandy for me, starting with the code you posted. I'd recommend trying the suggested remedies again.

commented: This solved the issue I was having. +1
commented: Great! +13

The first suggestion worked dandy for me, starting with the code you posted. I'd recommend trying the suggested remedies again.

I tried it again, and now the first one works fine... I must have not changed it properly. I don't know if it's going to be acceptable to define the function in the .h file, but they'll have to live with it. Thanks to everyone for all their help!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.