Help with template friend and ostream, I think I am close

Discussion in 'C++' started by truce, Jan 13, 2006.

  1. truce

    truce Guest

    I searched but couldn't find anything _quite_ like this. I have some
    code I inherited that needs some work. Basically I have a template
    that is instantiated in the c++ code and so only the headers are
    distributed. That works great, the only problem is that I cant get
    the friend ostream inserter operator to work correctly. Basically
    it never is instantiated so it never shows up in the library. Here is
    a (close to) minimum example demonstrating the problem. I want
    to be able to do this without having all the code in the header since
    I know what instances I will need. Thanks in advance -- I believe
    I am close on this, but just can't quite get it.

    // Foo.hh
    using namespace::std;
    #include <iostream>

    template<int> class Foo;
    template<int mp>
    std::eek:stream & operator<< (std::eek:stream&, const Foo<mp> &);

    template<int mp>
    class Foo {
    char x[mp];
    friend std::eek:stream & operator<< <>(std::eek:stream&,const Foo<mp> &);

    // end of Foo.hh


    #include "Foo.hh"

    template<int mp>
    int i;
    for (i=0;i<mp;i++);
    x = i;

    template<int mp>
    std::eek:stream & operator<< (std::eek:stream&, const Foo<mp> &)
    cout << "Nothing" << endl;

    template class Foo<2>;

    // end of

    If I try to link this code when trying to use cout with an instance of

    /tmp/test/ undefined reference to `std::basic_ostream<char,
    std::char_traits<char> >& operator<< <(int)2>(std::basic_ostream<char,
    std::char_traits<char> >&, Foo<(int)2> const&)'

    And to confirm an nm on the object file Foo.o gives me:

    nm --demangle Foo.o
    00000054 t global constructors keyed to _ZN3FooILi2EEC1EvFoo.ccAPePOb
    00000000 t __static_initialization_and_destruction_0(int, int)
    00000000 W Foo<2>::Foo()
    00000000 W Foo<2>::Foo()
    U std::ios_base::Init::Init()
    U std::ios_base::Init::~Init()
    00000000 b std::__ioinit
    U __cxa_atexit
    U __dso_handle
    U __gxx_personality_v0
    00000040 t __tcf_0
    truce, Jan 13, 2006
    1. Advertisements

  2. truce

    Earl Purple Guest

    The friend part is done correctly, the error is in here:
    Unless you and everyone you distribute to uses a compiler that can
    "export" templates, you cannot do that.

    And then you'd have to use the export keyword.
    Earl Purple, Jan 13, 2006
    1. Advertisements

  3. The friendship of the output operator is not related to your problem.

    If you are really sure you know all instantiations of Foo<>:
    be sure to call all related functions in

    Regards, Stephan
    =?iso-8859-1?q?Stephan_Br=F6nnimann?=, Jan 13, 2006
  4. truce

    truce Guest

    This is the part that I dont understand. I dont know how to force
    the operator function. I do know how to force the template though.

    In instantiate the objects for Foo of any type that I will ever use.
    This makes g++ generate all of the code in the template for any
    instances of Foo<2>. When compiled with the -fno-implicit-templates
    flag, the code is not needed in the header file. So I can write another
    piece of code, say such as this and link successfully even though
    at the time of compilation, it does not generate the code. It is already
    in Foo.o.

    #include "Foo.hh"
    int main(void) {
    Foo<2> xyz;

    But clearly, this usage doesn't force the friend function to get
    instantiated that is why it does not link successfully. That is what I am
    trying to force. In the same way that template class Foo<2> forces the
    compiler to include all the code for the class, I want to force the friend
    function to be compiled as well.

    I did not get the other posters mention of the export keyword. But I
    distribute the library, headers, Makefile, and the cross compiler as a
    toolkit so I do know what they are using.
    truce, Jan 13, 2006
  5. [OT]
    The option -fno-implicit-templates is specific to g++
    as well as its effects (I don't read the man page your way).
    Just for fun: compile with g++-3.3 and g++4.0, compare the

    By this your problem gets compiler (and most probaly version) specific:
    How do I explictly instantiate a function template?
    Regards, Stephan
    =?iso-8859-1?q?Stephan_Br=F6nnimann?=, Jan 13, 2006
  6. truce

    truce Guest

    Tried your test. g++ 4.0.2, 3.3.5, and 3.4.4 all did
    the *exact* same thing and worked correctly.
    All three allowed me to compile the implementation
    file and link against my main object.

    Further, I figured out how to do it .... for the benefit of
    those who run across the same opportunity and want to
    distribute headers + a library using templates.

    // At the bottom of
    // create the code for the template
    template class Foo<2>;
    // create the code for the operator
    template ostream& operator << (ostream&, const Foo<2>&);
    truce, Jan 14, 2006
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.