**I know my mistake is in the code, not the g++ linking arguments, because g++ isn't complaining about the constructor or thisWorks() member function. Furthermore, commenting out main.cpp lines 10&11 (operator<< lines) makes it compile just fine.**

Templates and I haven't gotten along well in the past, and I've been able to generally avoid them. I'm betting my error is something that will be semi-obvious to people who use templates semi-regularly.


The code block for file "allInOne.cpp" compiles, and outputs:
Code:
HEADER
Hello
Hello, again
The code block for files "main.cpp", "myLib.h", "myLib.cpp" fails compilation, giving:
Code:
main.cpp:10: undefined reference to `myLib::myOutput& myLib::operator<< <char [6]>(myLib::myOutput&, char const (&) [6])'
main.cpp:11: undefined reference to `myLib::myOutput& myLib::operator<< <char [13]>(myLib::myOutput&, char const (&) [13])'

(Note: I am aware that using my object by reference or pointer sliced to an ostream will break my invariant, and that I need to re-do my design. superbonzo pointed this out to me at http://forums.codeguru.com/showthrea...40#post2066940 )


So, this works fine:
Code:
########## FILE allInOne.cpp ##########

#include <iostream>
using namespace std;



namespace myLib {

class myOutput : public std::ostream {
   public:
      myOutput();
      void thisWorks();
      template <typename T>
      friend myOutput& operator<<(myOutput& myo, const T& v);
   private:
      void displayHeader();
      bool displayedHeader;
};

myOutput::myOutput() : ostream(cout.rdbuf()), displayedHeader(false) {
}

void myOutput::thisWorks() {
}

template <typename T>
myOutput& operator<<(myOutput& myo, const T& v) {
   myo.displayHeader();
   static_cast<std::ostream&>(myo) << v;
   return myo;
}

void myOutput::displayHeader() {
   if(false == displayedHeader) {
      static_cast<ostream&>(*this) << "HEADER" << endl;
      displayedHeader = true;
   }
}

}

using namespace myLib;



int main() {
   myOutput output;
   output.thisWorks();
   output << "Hello" << endl;
   output << "Hello, again" << endl;
}
Moving this into a library is when it gives compilation errors...
Code:
########## FILE main.cpp ##########

#include <myLib.h>
using namespace myLib;

#include <iostream>
using namespace std;

int main() {
   myOutput output;
   output.thisWorks();
   output << "Hello" << endl;
   output << "Hello, again" << endl;
}
Code:
########## FILE myLib.h ##########

#ifndef __MYLIB__
#define __MYLIB__

#include <iostream>

namespace myLib {

class myOutput : public std::ostream {
   public:
      myOutput();
      void thisWorks();
      template <typename T>
      friend myOutput& operator<<(myOutput& myo, const T& v);
   private:
      void displayHeader();
      bool displayedHeader;
};

}

#endif
Code:
########## FILE myLib.cpp ##########

#include <myLib.h>
using namespace myLib;

using namespace std;

namespace myLib {

myOutput::myOutput() : ostream(cout.rdbuf()), displayedHeader(false) {
}

void myOutput::thisWorks() {
}

template <typename T>
myOutput& operator<<(myOutput& myo, const T& v) {
   myo.displayHeader();
   static_cast<std::ostream&>(myo) << v;
   return myo;
}

void myOutput::displayHeader() {
   if(false == displayedHeader) {
      static_cast<ostream&>(*this) << "HEADER" << endl;
      displayedHeader = true;
   }
}

}