473,727 Members | 1,989 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Template friend function injection

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("Functio n()"); 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("Functio n()"); 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 '08 #1
21 4738
H9************* *@spambox.us 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("Functio n()"); 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("Functio n()"); getchar(); }
Marcel
Jul 11 '08 #2
Marcel Müller wrote:
[..]
Inline functions must be defined before their use. There is no way
around this.
[..]
So, you're saying that the following should not compile/link?

int foo();
int main()
{
return foo();
}
inline int foo() { return 0; } // note the 'inline'

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 '08 #3
On Jul 11, 5:37*pm, Marcel Müller <news.5.ma...@s pamgourmet.org>
wrote:
>
Obviously you are calling an external version of Function here.
template <typename T>
class Test
{
public:
* *friend void Function() { printf("Functio n()"); 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-lit...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("Functio n()"); 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 '08 #4
On Jul 11, 4:30*pm, H9XLrv5oXVNvH.. .@spambox.us 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
Jul 11 '08 #5
On Jul 11, 6:09*pm, gpderetta <gpdere...@gmai l.comwrote:
On Jul 11, 4:30*pm, H9XLrv5oXVNvH.. .@spambox.us wrote:
<snip>As you know when you define a class (with no template) and withinthe
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 '08 #6
gpderetta wrote:
On Jul 11, 4:30 pm, H9XLrv5oXVNvH.. .@spambox.us 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
Jul 11 '08 #7
On Jul 11, 6:37*pm, Victor Bazarov <v.Abaza...@com Acast.netwrote:
gpderetta wrote:
On Jul 11, 4:30 pm, H9XLrv5oXVNvH.. .@spambox.us 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 '08 #8
H9************* *@spambox.us wrote:
On Jul 11, 5:37 pm, Marcel Müller <news.5.ma...@s pamgourmet.org>
wrote:
>Obviously you are calling an external version of Function here.
>>template <typename T>
class Test
{
public:
friend void Function() { printf("Functio n()"); 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
Jul 11 '08 #9
On Jul 11, 6:53*pm, Marcel Müller <news.5.ma...@s pamgourmet.org>
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 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
12533
by: Christophe Barbe | last post by:
I am not clear about friend functions of a template class. GCC (3.3.2) wants me to add <> after the friend function names in the class declaration and VisualC++ doesn't like that. template <class T> class test{ test(void); ~test(void); friend bool operator== <> (const test<T> &p1, const test<T> &p2); }
2
10159
by: Christophe Barbe | last post by:
I posted a few days ago about the same problem but was not very clear. So here is my second take at it. Basically with GCC 3.3.2, I can't compile the example from the C++ FAQ Lite available online at http://www.parashift.com/c++-faq-lite/containers-and-templates.html#faq-34.15 Below are the two files that I compile with g++ foo.cpp -o foo or
1
4445
by: Dmitry D | last post by:
Hi all, I'm having problems with declaring a template friend function. It seems like I've done everything as explained in C++ FAQ, but still, I'm getting the linker error (unresolved external 'aFunc(A<char> const&)' ) in the following sample program. Tried it on GCC and Borland's compiler. Can somebody please show me the correct way to fix this? Thanks, Dmitry
5
2718
by: Trevor Lango | last post by:
What is the appropriate syntax for placing a friend function that includes as one of it's parameters a pointer to the class object itself within the template class? I have the following: //**************************************************** // testClass.h //**************************************************** #ifndef TESTCLASS_H
5
2639
by: Ruben Campos | last post by:
Some questions about this code: template <typename T> class MyTemplate; template <typename T> MyTemplate <T> operator- (const MyTemplate <T> & object); template <typename T> MyTemplate <T> operator- (const MyTemplate <T> & object1, const MyTemplate <T> & object2); template <typename T> class MyTemplate
3
3758
by: Hamilton Woods | last post by:
Diehards, I developed a template matrix class back around 1992 using Borland C++ 4.5 (ancestor of C++ Builder) and haven't touched it until a few days ago. I pulled it from the freezer and thawed it out. I built a console app using Microsoft Visual C++ 6 (VC++) and it worked great. Only one line in the header file had to be commented out. I built a console app using Borland C++ Builder 5. The linker complained of references to...
4
774
by: fdmfdmfdm | last post by:
I have the following code: #include <iostream> #include <cstdlib> #include <cassert> using namespace std; template <class T> class Stack{ public: enum{DefaultStack = 10, EmptyStack = -1};
9
2202
by: neildferguson | last post by:
I am using templates with a little project I am working on. My compiler (GCC) is finding a particular construct ambiguous. Can anyone suggest something I might change in the declaration of class Length so that I can use operator+ the way I'd like? //========================================= // File lentest.h: #ifndef FDIMENS_LENGTH_INCL #define FDIMENS_LENGTH_INCL
9
2063
by: wo3kie | last post by:
#include <iostream> #include <map> #include <utility> // // Base // / | \ // Derived1 Derived2 \ // \ | / // Derived3
0
9259
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9182
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9120
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8101
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6702
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6011
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4521
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4785
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2157
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.