linker errors when I use template friends?

Discussion in 'C++' started by John Harrison, May 16, 2004.

  1. "william xuuu" <> wrote in message news:...
    >
    > Actually, I also got linker errors with template functions and template
    > classes. And I avoided both of them successfully, by pouring foo.cpp
    > into foo.h, according to the C++ FAQ.
    >
    > (http://www.parashift.com/c -faq-lite/containers-and-templates.html)
    >
    > And then, I pre-declared each template friend function above the
    > definition of template class. But I still get template friends linker
    > error. My compiler is gcc 3.3.3. Any hints? Thanks,
    >


    Probably your 'pre-declaration' is not the same as your actual definition.
    So the linker tries to find the definiton for you pre-declaration and finds
    nothing. Show us the code.

    Don't #include foo.cpp in foo.h, that just makes things unnecessarily
    complicated. Put everthing into foo.h and throw away foo.cpp. You know it
    makes sense.

    john
     
    John Harrison, May 16, 2004
    #1
    1. Advertising

  2. John Harrison

    william xuuu Guest

    Actually, I also got linker errors with template functions and template
    classes. And I avoided both of them successfully, by pouring foo.cpp
    into foo.h, according to the C++ FAQ.

    (http://www.parashift.com/c -faq-lite/containers-and-templates.html)

    And then, I pre-declared each template friend function above the
    definition of template class. But I still get template friends linker
    error. My compiler is gcc 3.3.3. Any hints? Thanks,

    --
    William Xuuu
     
    william xuuu, May 16, 2004
    #2
    1. Advertising

  3. John Harrison

    William Xuuu Guest

    "John Harrison" <> writes:

    > Probably your 'pre-declaration' is not the same as your actual definition.
    > So the linker tries to find the definiton for you pre-declaration and finds
    > nothing. Show us the code.


    Okay, here it is: (only two files)
    //----------------------- "vector_set.h"

    //pre declarations.
    template <typename T> class Vector_Set;
    template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
    const Vector_Set<T>& s2);

    //begin class itself
    template <typename T> class Vector_Set
    {
    friend Vector_Set<T> operator+ (const Vector_Set<T>& s1, const
    Vector_Set<T>& s2);
    public:
    ...
    };

    // friends implementation
    template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
    const Vector_Set<T>& s2)
    {
    ...
    }

    //----------------------- "vector_set_main.cpp"

    typedef Vector_Set<int> Set;

    Set a = Set(10), b = Set(10);
    for(int i = 0; i < a.size(); i++)
    if(i % 2 == 1)
    a.add_member(i);
    else
    b.add_member(i);

    // Here causes error!
    a + b;



    warnings and errors:

    g++ -c vector_set_main.cpp
    In file included from vector_set_main.cpp:8:
    vector_set.h:29: warning: friend declaration `Vector_Set<T> operator+(const
    Vector_Set<T>&, const Vector_Set<T>&)' declares a non-template function
    g++ -g vector_set_main.o -O2 -lm -o vector_set_main
    vector_set_main.o(.text+0x172): In function `main':
    : undefined reference to `operator+(Vector_Set<int> const&, Vector_Set<int> const&)'

    does this help?

    --
    William Xuuu
     
    William Xuuu, May 16, 2004
    #3
  4. > template <typename T> class Vector_Set
    > {
    > friend Vector_Set<T> operator+ (const Vector_Set<T>& s1, const
    > Vector_Set<T>& s2);


    This is a non-template function. It declares (as a friend) this function

    Vector_Set<int> operator+ (const Vector_Set<int>& s1, const Vector_Set<int>&
    s2);

    >
    > typedef Vector_Set<int> Set;
    >
    > Set a = Set(10), b = Set(10);
    > for(int i = 0; i < a.size(); i++)
    > if(i % 2 == 1)
    > a.add_member(i);
    > else
    > b.add_member(i);
    >
    > // Here causes error!
    > a + b;
    >


    Now the compiler thinks there are two functions to choose from, the
    non-template (which you declared as a friend)

    Vector_Set<int> operator+ (const Vector_Set<int>& s1, const Vector_Set<int>&
    s2);

    and the template (which you pre-declared)

    template <class T>
    Vector_Set<T> operator+ (const Vector_Set<T>& s1, const Vector_Set<T>& s2);

    Given this choice the compiler always prefers the non-template. But since
    you didn't define a non-template you get a link error.

    The answer is to tell the compiler that the friend declaration refers to a
    template function. You do that by adding '<T>' or '<>' after operator+.

    template <typename T> class Vector_Set
    {
    friend Vector_Set<T> operator+ <>(const Vector_Set<T>& s1, const
    Vector_Set<T>& s2);

    It's easy to forget that you can have template and non-template versions of
    the same function.

    john
     
    John Harrison, May 16, 2004
    #4
  5. > The answer is to tell the compiler that the friend declaration refers to a
    > template function. You do that by adding '<T>' or '<>' after operator+.
    >


    Hmm, seems gcc doesn't always handle the <T> form correctly. I would stick
    with <>.

    john
     
    John Harrison, May 16, 2004
    #5
  6. John Harrison

    Greg Comeau Guest

    In article <>, William Xuuu <> wrote:
    >"John Harrison" <> writes:
    >> Probably your 'pre-declaration' is not the same as your actual definition.
    >> So the linker tries to find the definiton for you pre-declaration and finds
    >> nothing. Show us the code.

    >
    >Okay, here it is: (only two files)
    >//----------------------- "vector_set.h"
    >
    >//pre declarations.
    >template <typename T> class Vector_Set;
    >template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
    > const Vector_Set<T>& s2);
    >
    >//begin class itself
    >template <typename T> class Vector_Set
    >{
    >friend Vector_Set<T> operator+ (const Vector_Set<T>& s1, const
    > Vector_Set<T>& s2);
    >public:
    > ...
    >};
    >
    >// friends implementation
    >template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
    > const Vector_Set<T>& s2)
    >{
    > ...
    >}
    >
    >//----------------------- "vector_set_main.cpp"
    >
    > typedef Vector_Set<int> Set;
    >
    > Set a = Set(10), b = Set(10);
    > for(int i = 0; i < a.size(); i++)
    > if(i % 2 == 1)
    > a.add_member(i);
    > else
    > b.add_member(i);
    >
    > // Here causes error!
    > a + b;
    >
    >
    >
    >warnings and errors:
    >
    >g++ -c vector_set_main.cpp
    >In file included from vector_set_main.cpp:8:
    >vector_set.h:29: warning: friend declaration `Vector_Set<T> operator+(const
    > Vector_Set<T>&, const Vector_Set<T>&)' declares a non-template function
    >g++ -g vector_set_main.o -O2 -lm -o vector_set_main
    >vector_set_main.o(.text+0x172): In function `main':
    >: undefined reference to `operator+(Vector_Set<int> const&, Vector_Set<int> const&)'
    >
    >does this help?


    Like John and your warning say: the decl is not the same
    as the definition. Your fried declares a non-template op+ however
    your definition is for a template one. Figure out which you
    need and use the same for both.
    --
    Greg Comeau / Comeau C++ 4.3.3, for C++03 core language support
    Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
    World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
    Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
     
    Greg Comeau, May 16, 2004
    #6
  7. John Harrison

    William Xuuu Guest

    "John Harrison" <> writes:

    >> The answer is to tell the compiler that the friend declaration refers to a
    >> template function. You do that by adding '<T>' or '<>' after operator+.
    >>


    Hmm, it works fine by adding <> or <T> as follows.

    //begin class itself
    template <typename T> class Vector_Set
    {

    friend Vector_Set<T> operator+<T> (const Vector_Set<T>& s1, const
    Vector_Set<T>& s2);
    };

    While, the C++ FAQ didn't add <> or <T> ?!

    Then I find it's not allowed to use + as:

    a +<int> b;

    So ?

    > Hmm, seems gcc doesn't always handle the <T> form correctly. I would stick
    > with <>.


    Could you explain the differences between <T> and <> ?

    And, i find that either adding <T> after pre-declaration or its
    implementation, as:

    //pre declarations.
    template <typename T> class Vector_Set;
    template <typename T> Vector_Set<T> operator+<T> (const Vector_Set<T>& s1,
    const Vector_Set<T>& s2);


    // friends implementation
    template <typename T> Vector_Set<T> operator+<T> (const Vector_Set<T>& s1,
    const Vector_Set<T>& s2)
    { ... }


    both would cause same error:

    error: partial specialization `operator+<T>' of function template

    Why would it happen?

    --
    William Xuuu
     
    William Xuuu, May 17, 2004
    #7
  8. John Harrison

    Greg Comeau Guest

    In article <>, William Xuuu <> wrote:
    >"John Harrison" <> writes:
    >
    >>> The answer is to tell the compiler that the friend declaration refers to a
    >>> template function. You do that by adding '<T>' or '<>' after operator+.
    >>>

    >
    >Hmm, it works fine by adding <> or <T> as follows.
    >
    >//begin class itself
    >template <typename T> class Vector_Set
    >{
    >
    >friend Vector_Set<T> operator+<T> (const Vector_Set<T>& s1, const
    > Vector_Set<T>& s2);
    >};
    >
    >While, the C++ FAQ didn't add <> or <T> ?!
    >
    >Then I find it's not allowed to use + as:
    >
    > a +<int> b;
    >
    >So ?


    Not sure what you're asking, but perhaps you're looking for
    the long-hand version like a.operator+<int>(b);

    >
    >> Hmm, seems gcc doesn't always handle the <T> form correctly. I would stick
    >> with <>.

    >
    >Could you explain the differences between <T> and <> ?
    >
    >And, i find that either adding <T> after pre-declaration or its
    >implementation, as:
    >
    >//pre declarations.
    >template <typename T> class Vector_Set;
    >template <typename T> Vector_Set<T> operator+<T> (const Vector_Set<T>& s1,
    > const Vector_Set<T>& s2);
    >
    >
    >// friends implementation
    >template <typename T> Vector_Set<T> operator+<T> (const Vector_Set<T>& s1,
    > const Vector_Set<T>& s2)
    >{ ... }
    >
    >
    >both would cause same error:
    >
    >error: partial specialization `operator+<T>' of function template
    >
    >Why would it happen?


    Because a "primary" template declaration should not mention
    it's arguments on its name, which the <T> would do above, but
    since it's declared above, the friend is using it in your case,
    not declaring it as such.
    --
    Greg Comeau / Comeau C++ 4.3.3, for C++03 core language support
    Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
    World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
    Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
     
    Greg Comeau, May 17, 2004
    #8
  9. John Harrison

    William Xuuu Guest

    (Greg Comeau) writes:

    >>Hmm, it works fine by adding <> or <T> as follows.
    >>
    >>//begin class itself
    >>template <typename T> class Vector_Set
    >>{
    >>
    >>friend Vector_Set<T> operator+<T> (const Vector_Set<T>& s1, const
    >> Vector_Set<T>& s2);
    >>};
    >>
    >>While, the C++ FAQ didn't add <> or <T> ?!
    >>
    >>Then I find it's not allowed to use + as:
    >>
    >> a +<int> b;
    >>
    >>So ?

    >
    > Not sure what you're asking, but perhaps you're looking for
    > the long-hand version like a.operator+<int>(b);
    >


    Right, a.operator+<int>(b), when we declare it to be a member of a
    class. But here it's declared as a friend function! So don't we have to
    specifly <T> as well? i.e, a +<int> b

    --
    William Xuuu
     
    William Xuuu, May 17, 2004
    #9
  10. "William Xuuu" <> wrote in message news:...
    > "John Harrison" <> writes:
    >
    > >> The answer is to tell the compiler that the friend declaration refers

    to a
    > >> template function. You do that by adding '<T>' or '<>' after operator+.
    > >>

    >
    > Hmm, it works fine by adding <> or <T> as follows.
    >


    The following code produces compiler errors on gcc.

    #include <iostream>
    using namespace std;

    template <typename T> class Vector_Set;
    template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
    const Vector_Set<T>& s2);

    template <typename T> class Vector_Set
    {
    friend Vector_Set<T> operator+ <T> (const Vector_Set<T>& s1, const
    Vector_Set<T>& s2);
    };

    template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
    const Vector_Set<T>& s2)
    {
    return s1;
    }

    int main()
    {
    typedef Vector_Set<int> Set;
    Set a, b;
    a + b;
    }

    Change <T> to <> in the friend declaration and it compiles, remove using
    namespace std and it compiles. I think its a gcc bug.

    john
     
    John Harrison, May 17, 2004
    #10
  11. > >>
    > >>Then I find it's not allowed to use + as:
    > >>
    > >> a +<int> b;
    > >>
    > >>So ?

    > >
    > > Not sure what you're asking, but perhaps you're looking for
    > > the long-hand version like a.operator+<int>(b);
    > >

    >
    > Right, a.operator+<int>(b), when we declare it to be a member of a
    > class. But here it's declared as a friend function! So don't we have to
    > specifly <T> as well? i.e, a +<int> b
    >


    I think you're confused, a.operator+<int>(b) isn't a declaration, its a
    function call.

    a + b works because in C++ the template function to call is deduced from the
    types of the arguments. You can specify the type by appending them after the
    function name

    func<int>(a, b)

    if you want or need to be explicit about template parameters but this syntax
    isn't available for the operator form of a function call, which is why Greg
    advised

    a.operator+<int>(b)

    john
     
    John Harrison, May 18, 2004
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. fabio de francesco

    errors = templates * friends;

    fabio de francesco, Jun 24, 2004, in forum: C++
    Replies:
    7
    Views:
    350
    fabio de francesco
    Jun 28, 2004
  2. BigMan
    Replies:
    4
    Views:
    3,667
    Malte Starostik
    Mar 29, 2005
  3. Replies:
    2
    Views:
    609
  4. Replies:
    4
    Views:
    410
  5. Replies:
    0
    Views:
    676
Loading...

Share This Page