Template friend function injection

Discussion in 'C++' started by H9XLrv5oXVNvHiUI@spambox.us, Jul 11, 2008.

  1. Guest

    Hi, I have a question about injecting friend functions within template
    classes. My question is specific to gcc (version 3.4.5) used in
    combination with mingw because this code (or at least code that gets
    the same result) works as expected in visualc++. I know that this is
    probably not the right behavior for a compiler but it's the kind of
    behavior I'm searching for so I was hoping there was a way to do the
    same thing in gcc.
    As you know when you define a class (with no template) and within the
    class you define a friend function, the function is injected in the
    scope directly outside of the class itself.

    --- code ---

    void Function();

    int main(int argc, char* argv[])
    {
    Function(); // This works
    }

    class Test
    {
    public:
    friend void Function() { printf("Function()"); getchar(); }
    };

    -- end code --


    Now I would like to mimic the same behavior with template classes, but
    this code doesn't work:

    -- code --

    void Function();

    int main(int argc, char* argv[])
    {
    Function(); // This does not work
    }

    template <typename T>
    class Test
    {
    public:
    friend void Function() { printf("Function()"); getchar(); }
    };

    template class Test<int>;

    -- end code --

    Specifically I receive an error at link time about Function() not
    being defined, which I guess is due to the compiler not considering
    the definition of Function to be a non-template function and instead
    assuming it to be a template function just because it's defined inside
    of a template class.
    Now, the funny thing is that if you move the main() BELOW the explicit
    instantiation of the template class Test, this code actually compile
    and works, that's why I consider it to be a "bug" because
    theoretically if the definition of Function() is a template function
    (thus not a normal function) it should never be used for the call
    inside of the main() function, whether the main() function is below
    the instantiation or not. Am I right?
    Anyway I'm searching for a way to make the definition of Function()
    available for the main() function even if the main() function is above
    the template instantiation. Is there a way to accomplish this for gcc?
    Like some command-line flag or something? I'd really appreciate that.
    Thanks.
    , Jul 11, 2008
    #1
    1. Advertising

  2. wrote:
    > -- code --
    >
    > void Function();
    >
    > int main(int argc, char* argv[])
    > {
    > Function(); // This does not work
    > }


    Obviously you are calling an external version of Function here.


    > template <typename T>
    > class Test
    > {
    > public:
    > friend void Function() { printf("Function()"); getchar(); }


    Now you define Function inline. this is an error.

    > };
    >
    > template class Test<int>;
    >
    > -- end code --



    > Specifically I receive an error at link time about Function() not
    > being defined, which I guess is due to the compiler not considering
    > the definition of Function to be a non-template function and instead
    > assuming it to be a template function just because it's defined inside
    > of a template class.


    No. It is because Function is declared as extern so far which is
    obviously wrong.

    > Now, the funny thing is that if you move the main() BELOW the explicit
    > instantiation of the template class Test, this code actually compile
    > and works, that's why I consider it to be a "bug" because
    > theoretically if the definition of Function() is a template function
    > (thus not a normal function) it should never be used for the call
    > inside of the main() function, whether the main() function is below
    > the instantiation or not. Am I right?


    No. The second approach is valid code. You call Function after it is
    defined inline.

    > Anyway I'm searching for a way to make the definition of Function()
    > available for the main() function even if the main() function is above
    > the template instantiation. Is there a way to accomplish this for gcc?


    Inline functions must be defined before their use. There is no way
    around this.
    I would prefer to define Function outside the body of Test. Like that:


    void Function();

    int main(int argc, char* argv[])
    {
    Function(); // This does not work
    }

    template <typename T>
    class Test
    {
    public:
    friend void Function();
    };

    template class Test<int>;

    void Function()
    { printf("Function()"); getchar(); }


    Marcel
    Marcel Müller, Jul 11, 2008
    #2
    1. Advertising

  3. Guest

    On Jul 11, 5:37 pm, Marcel Müller <>
    wrote:
    >
    > Obviously you are calling an external version of Function here.
    >
    > > template <typename T>
    > > class Test
    > > {
    > > public:
    > >    friend void Function() { printf("Function()"); getchar(); }

    >
    > Now you define Function inline. this is an error.
    >


    Sorry, but why the function is defined as inline if I define it inside
    of a template and it is not if I define it inside of a normal class?


    >
    > No. It is because Function is declared as extern so far which is
    > obviously wrong.
    >


    Well, then this page is wrong (or at least confusing):
    http://www.parashift.com/c -faq-lite/templates.html#faq-35.16
    It says:
    "After the compiler sees that magic stuff, it will be better informed
    about the friend functions. In particular, it will realize that the
    friend lines are referring to functions that are themselves templates.
    That eliminates the confusion.

    Another approach is to define the friend function within the class
    body at the same moment you declare it to be a friend."

    >
    > No. The second approach is valid code. You call Function after it is
    > defined inline.
    >


    Then it means that the code in the first section (when the function
    Function() is defined within the non-template class) should be wrong
    too, and thus signaled by the compiler/linker, isn't it?

    >
    > Inline functions must be defined before their use. There is no way
    > around this.
    > I would prefer to define Function outside the body of Test. Like that:
    >
    > void Function();
    >
    > int main(int argc, char* argv[])
    > {
    >         Function(); // This does not work
    >
    > }
    >
    > template <typename T>
    > class Test
    > {
    > public:
    >         friend void Function();
    >
    > };
    >
    > template class Test<int>;
    >
    > void Function()
    > { printf("Function()"); getchar(); }
    >
    > Marcel


    Unluckily I can't do that because the whole purpose of this approach
    was to do something with T inside of the Function() function. Using
    templates so that the function is defined only at the very final
    moment when someone instantiate the Test class with some template
    argument.
    , Jul 11, 2008
    #3
  4. gpderetta Guest

    On Jul 11, 4:30 pm, wrote:
    <snip>
    > As you know when you define a class (with no template) and within the
    > class you define a friend function, the function is injected in the
    > scope directly outside of the class itself.
    >

    AFAIK friend injection is prestandard behavior. The standard requires
    friend functions defined inside a class *not* to
    be injected in the namespace the class is defined in. The only way to
    call such a function is via argument dependent lookup (thus a nullary
    inline friend function cannot be called at all). Older GCCs accepted
    such code by default, but this extension has been removed from recent
    GCCs. There might be an option to re-enable this feature , but it is
    better to fix the code.

    HTH,

    --
    gpd
    gpderetta, Jul 11, 2008
    #4
  5. Guest

    On Jul 11, 6:09 pm, gpderetta <> wrote:
    > On Jul 11, 4:30 pm, wrote:
    > <snip>> As you know when you define a class (with no template) and within the
    > > class you define a friend function, the function is injected in the
    > > scope directly outside of the class itself.

    >
    > AFAIK friend injection is prestandard behavior.  The standard requires
    > friend functions defined inside a class *not* to
    > be injected in the namespace the class is defined in. The only way to
    > call such a function is via argument dependent lookup (thus a nullary
    > inline friend function cannot be called at all). Older GCCs accepted
    > such code by default, but this extension has been removed from recent
    > GCCs. There might be an option to re-enable this feature , but it is
    > better to fix the code.
    >
    > HTH,
    >
    > --
    > gpd


    Well the problem is that I was hoping in this trick to use a
    particular technique.
    Also in the GCC documentation there's written that the thing that's
    not allowed is to declare AND define a friend function within a class,
    thus creating a new symbol and injecting the function itself.
    Instead you must first declare the function in the scope you're
    injecting it in and then you can "inject" just the body of that
    function and that's exactly what I'm doing. I could be wrong though,
    that's why I'm asking here if there's any way to accomplish this.
    , Jul 11, 2008
    #5
  6. Guest

    On Jul 11, 6:37 pm, Victor Bazarov <> wrote:
    > gpderetta wrote:
    > > On Jul 11, 4:30 pm, wrote:
    > > <snip>
    > >> As you know when you define a class (with no template) and within the
    > >> class you define a friend function, the function is injected in the
    > >> scope directly outside of the class itself.

    >
    > > AFAIK friend injection is prestandard behavior.  The standard requires
    > > friend functions defined inside a class *not* to
    > > be injected in the namespace the class is defined in.

    >
    > The difference with the OP's case, however, is that the function is
    > already in the namespace scope by virtue of having been declared there.
    >
    >  > The only way to
    >
    > > call such a function is via argument dependent lookup (thus a nullary
    > > inline friend function cannot be called at all). Older GCCs accepted
    > > such code by default, but this extension has been removed from recent
    > > GCCs. There might be an option to re-enable this feature , but it is
    > > better to fix the code.

    >
    > > HTH,

    >
    > > --
    > > gpd

    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask


    So does it mean that my syntax of function injection is standard-
    compliant? And do you know of a way to accomplish the same thing
    within the template class?
    , Jul 11, 2008
    #6
  7. wrote:
    > On Jul 11, 5:37 pm, Marcel Müller <>
    > wrote:
    >> Obviously you are calling an external version of Function here.
    >>
    >>> template <typename T>
    >>> class Test
    >>> {
    >>> public:
    >>> friend void Function() { printf("Function()"); getchar(); }

    >> Now you define Function inline. this is an error.
    >>

    >
    > Sorry, but why the function is defined as inline if I define it inside
    > of a template and it is not if I define it inside of a normal class?


    It is always inline. However in case of a normal class the compiler does
    not assume, that the function is not used by another object module in a
    way that does not allow inline - e.g. taking the address. Therefore the
    compiler always generates the code for the non-inline function and
    associates it with a weak symbol. If it is not used or if there are
    multiple implementations on linkage, the linker discards superfluous
    instances.
    In case of templates the compiler behaves different. Since templates
    have always to be defined before usage. The compiler generates the
    non-inline code only on demand in the current object module. The
    explicit template instantiation is not sufficient for that.


    >> No. The second approach is valid code. You call Function after it is
    >> defined inline.
    >>

    >
    > Then it means that the code in the first section (when the function
    > Function() is defined within the non-template class) should be wrong
    > too, and thus signaled by the compiler/linker, isn't it?


    No, that's fine. The compile only silently calls the non-inline version
    of Function because it does not yet have an implementation.

    However, Alf P.Steinbach is right. The standard does not make such
    restrictions. It mainly defines that it is not an error to have
    redundant symbols in different object modules in this case. It always up
    to the compiler to inline the code or not.
    But from the implementation point of view, it is obvious that you cannot
    inline a function before their definition. That would require a two-pass
    compilation.


    >> I would prefer to define Function outside the body of Test. Like that:

    >
    > Unluckily I can't do that because the whole purpose of this approach
    > was to do something with T inside of the Function() function. Using
    > templates so that the function is defined only at the very final
    > moment when someone instantiate the Test class with some template
    > argument.


    I expected something like that. That still gives you the chance, to use
    the functions defined inside Test not before the definition of test.

    Furthermore you can define a template version of Function outside Test
    for this purpose.


    Marcel
    Marcel Müller, Jul 11, 2008
    #7
  8. Guest

    On Jul 11, 6:53 pm, Marcel Müller <>
    wrote:

    > I expected something like that. That still gives you the chance, to use
    > the functions defined inside Test not before the definition of test.
    >
    > Furthermore you can define a template version of Function outside Test
    > for this purpose.
    >
    > Marcel


    Can you explain this point better? Especially the last sentence. If I
    define a template version of Function() then I would not be able to
    call it from main, am I wrong? Can you provide an example? Thank you.
    , Jul 11, 2008
    #8
  9. Guest

    On Jul 11, 7:21 pm, Victor Bazarov <> wrote:
    > wrote:
    > > [..]
    > > So does it mean that my syntax of function injection is standard-
    > > compliant? And do you know of a way to accomplish the same thing
    > > within the template class?

    >
    >  From all I could gather by reading the Standard and other posts, there
    > is nothing wrong with your code even when the template is involved.
    > [temp.friend]/5 says:
    > <quote>
    > When a function is defined in a friend function declaration in a class
    > template, the function is defined at each instantiation of the class
    > template. The function is defined even if it is never used. The same
    > restrictions on multiple declarations and definitions which apply to
    > non-template function declarations and definitions also apply to these
    > implicit definitions.
    > </quote>
    >
    > The function is inline (implicitly), it's defined (per that paragraph)
    > when you instantiate your template.
    >
    > VC++ 9 (Visual Studio 2008) chokes on the module throwing C1001 (ICE) on
    > the line that contains the friend declaration.  Why, I don't know.  I do
    > not know whether it's been already reported as a bug, either.  I'll ask
    > in the Visual C++ newsgroup.  As for GCC, you would have to ask them.
    > Comeau C++ (online) compiles it fine; it doesn't link, so I am not sure
    > if everything's OK with their ability to handle that code.
    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask


    So my code involving the template class and function injection is
    correct and standard-compliant.

    As for GCC it compiles the code just fine but as I said it doesn't
    link it because it misses the Function() function. It says that's not
    defined.
    Now I don't know if this is due to the function definition for some
    reason not "matching" the declaration (for instance because it is
    treated like a template function) or because somehow the function body
    is completely "skipped" (for instance because the function gets
    inlined).
    From what I know a function gets inlined only when declaration and
    definition occur in the same place, which is not true for my code.
    So is there any possibility that this is a GCC bug?
    , Jul 11, 2008
    #9
  10. Guest

    On Jul 11, 7:53 pm, Victor Bazarov <> wrote:
    > wrote:
    > > [..]
    > > So my code involving the template class and function injection is
    > > correct and standard-compliant.

    >
    > Yes, IMNSHO.
    >
    > > As for GCC it compiles the code just fine but as I said it doesn't
    > > link it because it misses the Function() function. It says that's not
    > > defined.
    > > Now I don't know if this is due to the function definition for some
    > > reason not "matching" the declaration (for instance because it is
    > > treated like a template function) or because somehow the function body
    > > is completely "skipped" (for instance because the function gets
    > > inlined).

    >
    > You probably can examine the contents of the object code (.o file) and
    > find out what functions you have defined there. I would be you have at
    > least 'main'. <Unix> RTFM about 'nm' (IIRC) utility. </Unix>
    >


    Yes, the problem is that on windows with mingw at least the object
    files are outputted on the temporary folder and deleted as far as the
    compilation fails. I guess there's some kind of command-line argument
    to tell gcc not to delete them or to put them somewhere I say it to,
    but I'm not very used to gcc so I'll have to find it out.

    > > From what I know a function gets inlined only when declaration and
    > > definition occur in the same place, which is not true for my code.

    >
    > Is that code different from what you posted?
    >


    I don't understand the question. I'm talking about the code I posted,
    which doesn't compile as well as my real code I'm working on.

    > > So is there any possibility that this is a GCC bug?

    >
    > Bug? In GCC?! Nah...
    >


    Well if Bush became president 2 consecutive times, everything is
    possible.

    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask
    , Jul 11, 2008
    #10
  11. Guest

    On Jul 11, 8:33 pm, Victor Bazarov <> wrote:
    > Victor Bazarov wrote:
    > > wrote:
    > >> On Jul 11, 7:53 pm, Victor Bazarov <> wrote:
    > >>> wrote:
    > >>>> [..]
    > >>>> From what I know a function gets inlined only when declaration and
    > >>>> definition occur in the same place, which is not true for my code.
    > >>> Is that code different from what you posted?

    >
    > >> I don't understand the question. I'm talking about the code I posted,
    > >> which doesn't compile as well as my real code I'm working on.

    >
    > > I wasn't sure whether you meant the code you posted or some other code
    > > in which the template and its explicit instantiation were in a different
    > > (than 'main') translation unit.  Can you try your code on a different
    > > compiler?  I am going to try in GCC on Linux.  Will report with results
    > > in a few minutes...

    >
    > Tried it with GCC 4.2.3 on Ubuntu.  Here's the output:
    >
    >      Ubuntu-bazarov:~$ g++ test_template.cpp
    >      /tmp/ccCNJWBg.o: In function `main':
    >      test_template.cpp:(.text+0x12): undefined reference to `Function()'
    >      collect2: ld returned 1 exit status
    >      Ubuntu-bazarov:~$ g++ -c test_template.cpp -o test_template.o
    >      Ubuntu-bazarov:~$ nm test_template.o
    >               U _Z8Functionv
    >               U __gxx_personality_v0
    >      00000000 T main
    >      Ubuntu-bazarov:~$
    >
    > As we can see, the function 'Function' does not get defined in the
    > module although the template Test is instantiated.  That looks like an
    > oversight on GCC part :*)
    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask


    Ok, so the function gets probably inlined? Could you try to copy/paste
    the printf() call many times so that the compiler doesn't inline it?
    Or is there somethin for not making GCC inline a function? I know on
    MSVC there's the __declspec(noinline) but I don't know if GCC has some
    equivalent (I guess it does though).
    , Jul 11, 2008
    #11
  12. Guest

    Also, I tried this on Open Watcom and it compiles and link it without
    any problem and the executable works of course.
    , Jul 11, 2008
    #12
  13. Guest

    On Jul 11, 8:44 pm, wrote:
    > On Jul 11, 8:33 pm, Victor Bazarov <> wrote:
    >
    >
    >
    > > Victor Bazarov wrote:
    > > > wrote:
    > > >> On Jul 11, 7:53 pm, Victor Bazarov <> wrote:
    > > >>> wrote:
    > > >>>> [..]
    > > >>>> From what I know a function gets inlined only when declaration and
    > > >>>> definition occur in the same place, which is not true for my code.
    > > >>> Is that code different from what you posted?

    >
    > > >> I don't understand the question. I'm talking about the code I posted,
    > > >> which doesn't compile as well as my real code I'm working on.

    >
    > > > I wasn't sure whether you meant the code you posted or some other code
    > > > in which the template and its explicit instantiation were in a different
    > > > (than 'main') translation unit.  Can you try your code on a different
    > > > compiler?  I am going to try in GCC on Linux.  Will report with results
    > > > in a few minutes...

    >
    > > Tried it with GCC 4.2.3 on Ubuntu.  Here's the output:

    >
    > >      Ubuntu-bazarov:~$ g++ test_template.cpp
    > >      /tmp/ccCNJWBg.o: In function `main':
    > >      test_template.cpp:(.text+0x12): undefined reference to `Function()'
    > >      collect2: ld returned 1 exit status
    > >      Ubuntu-bazarov:~$ g++ -c test_template.cpp -o test_template.o
    > >      Ubuntu-bazarov:~$ nm test_template.o
    > >               U _Z8Functionv
    > >               U __gxx_personality_v0
    > >      00000000 T main
    > >      Ubuntu-bazarov:~$

    >
    > > As we can see, the function 'Function' does not get defined in the
    > > module although the template Test is instantiated.  That looks like an
    > > oversight on GCC part :*)

    >
    > > V
    > > --
    > > Please remove capital 'A's when replying by e-mail
    > > I do not respond to top-posted replies, please don't ask

    >
    > Ok, so the function gets probably inlined? Could you try to copy/paste
    > the printf() call many times so that the compiler doesn't inline it?
    > Or is there somethin for not making GCC inline a function? I know on
    > MSVC there's the __declspec(noinline) but I don't know if GCC has some
    > equivalent (I guess it does though).


    Nop, even with the attribute __attribute__ ((noinline)) it still gives
    that error about Function() not being defined.
    , Jul 11, 2008
    #13
  14. wrote:
    > On Jul 11, 6:53 pm, Marcel Müller <>
    > wrote:
    >
    >> I expected something like that. That still gives you the chance, to use
    >> the functions defined inside Test not before the definition of test.
    >>
    >> Furthermore you can define a template version of Function outside Test
    >> for this purpose.
    >>
    >> Marcel

    >
    > Can you explain this point better? Especially the last sentence. If I
    > define a template version of Function() then I would not be able to
    > call it from main, am I wrong? Can you provide an example? Thank you.


    template <typename T>
    void Function(const T& arg);

    template <typename T>
    class Test
    {
    public:
    friend void Function<T>(const T&);
    };

    template <typename T>
    void Function(const T& arg)
    { printf("Function()"); getchar(); }

    int main(int argc, char* argv[])
    {
    Function(Test<int>());
    }


    But from your question I guess that you want to do something entirely
    different. You want to control by the statement
    template class Test<int>;
    which version of Function is implemented, isn't it? The argument list of
    Function does not depend on T at all, but the body does. This is evil.
    Think what is happening if you write
    template class Test<int>;
    template class Test<char>;

    You will get an error in this case, but only if both of them are defined
    in the same module. Otherwise you violate the ODR and get undefined
    behavior.

    In this case a simple
    typedef int myFunctionType;
    would do a better job.


    Marcel
    Marcel Müller, Jul 11, 2008
    #14
  15. Guest

    On Jul 11, 9:27 pm, Marcel Müller <>
    wrote:
    > wrote:
    > > On Jul 11, 6:53 pm, Marcel Müller <>
    > > wrote:

    >
    > >> I expected something like that. That still gives you the chance, to use
    > >> the functions defined inside Test not before the definition of test.

    >
    > >> Furthermore you can define a template version of Function outside Test
    > >> for this purpose.

    >
    > >> Marcel

    >
    > > Can you explain this point better? Especially the last sentence. If I
    > > define a template version of Function() then I would not be able to
    > > call it from main, am I wrong? Can you provide an example? Thank you.

    >
    > template <typename T>
    > void Function(const T& arg);
    >
    > template <typename T>
    > class Test
    > {
    > public:
    >         friend void Function<T>(const T&);
    >
    > };
    >
    > template <typename T>
    > void Function(const T& arg)
    > { printf("Function()"); getchar(); }
    >
    > int main(int argc, char* argv[])
    > {
    >         Function(Test<int>());
    >
    > }
    >
    > But from your question I guess that you want to do something entirely
    > different. You want to control by the statement
    >    template class Test<int>;
    > which version of Function is implemented, isn't it? The argument list of
    > Function does not depend on T at all, but the body does. This is evil.
    > Think what is happening if you write
    >    template class Test<int>;
    >    template class Test<char>;
    >
    > You will get an error in this case, but only if both of them are defined
    > in the same module. Otherwise you violate the ODR and get undefined
    > behavior.
    >
    > In this case a simple
    >    typedef int myFunctionType;
    > would do a better job.
    >
    > Marcel


    Yes I know most of the times this would be seen as a bad design choice
    but in this case is instead a perfect solution to a problem because I
    know as a design principle that the Test class template will never be
    instantiated more than one time so there won't be any duplicate
    definition of Function(). Also if you follow the conversation with
    Victor Bazarov he informed me that my code is completely standard-
    compliant thus making this a possible GCC bug. I've also double-
    checked that this code compiles and links fine on the Open Watcom
    compiler.
    , Jul 11, 2008
    #15
  16. Guest

    On Jul 11, 8:51 pm, wrote:
    > Also, I tried this on Open Watcom and it compiles and link it without
    > any problem and the executable works of course.


    Furthermore I was wrong about having a way to compile this code in
    visualc++. In fact that code was slightly different and visualc++
    seems not only unable to compile any kind of code like this, but it
    also crashes when you try to make it to.
    So basically so far the only compiler able to compile this kind of
    code seems to be this Open Watcom.
    , Jul 11, 2008
    #16
    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. Yueh-Wei Hu
    Replies:
    0
    Views:
    435
    Yueh-Wei Hu
    May 23, 2004
  2. Replies:
    0
    Views:
    471
  3. Replies:
    2
    Views:
    462
    John Harrison
    Nov 9, 2005
  4. A L
    Replies:
    1
    Views:
    495
    Alf P. Steinbach /Usenet
    Aug 25, 2010
  5. moogyd
    Replies:
    5
    Views:
    810
    James Kanze
    Oct 26, 2010
Loading...

Share This Page