Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Template instantiation context (http://www.velocityreviews.com/forums/t691698-template-instantiation-context.html)

Juha Nieminen 07-18-2009 05:27 PM

Template instantiation context
 
Assume we have these three files:

//--------------------------------------------------------------
// foo.hh
#include <iostream>

template<typename T>
void foo(T value)
{
static int s = 0;
++s;
std::cout << "value:" << value << ", s:" << s
<< ", externalVar:" << externalVar << std::endl;
}
//--------------------------------------------------------------

//--------------------------------------------------------------
// bar.cc
namespace { const int externalVar = 456; }
#include "foo.hh"

void bar()
{
std::cout << "In bar(): ";
foo(200);
}
//--------------------------------------------------------------

//--------------------------------------------------------------
// test.cc
namespace { const int externalVar = 123; }
#include "foo.hh"

void bar();

int main()
{
std::cout << "In main(): ";
foo(100);
bar();
}
//--------------------------------------------------------------

Now we compile test.cc and bar.cc into an executable program. What
should be the output of this program?

Alf P. Steinbach 07-18-2009 05:43 PM

Re: Template instantiation context
 
* Juha Nieminen:
> Assume we have these three files:
>
> //--------------------------------------------------------------
> // foo.hh
> #include <iostream>
>
> template<typename T>
> void foo(T value)
> {
> static int s = 0;
> ++s;
> std::cout << "value:" << value << ", s:" << s
> << ", externalVar:" << externalVar << std::endl;
> }
> //--------------------------------------------------------------
>
> //--------------------------------------------------------------
> // bar.cc
> namespace { const int externalVar = 456; }
> #include "foo.hh"
>
> void bar()
> {
> std::cout << "In bar(): ";
> foo(200);
> }
> //--------------------------------------------------------------
>
> //--------------------------------------------------------------
> // test.cc
> namespace { const int externalVar = 123; }
> #include "foo.hh"
>
> void bar();
>
> int main()
> {
> std::cout << "In main(): ";
> foo(100);
> bar();
> }
> //--------------------------------------------------------------
>
> Now we compile test.cc and bar.cc into an executable program. What
> should be the output of this program?


It's UB.

Btw., please don't formulate real questions so that they sound like homework.

If this question had any other answer than UB I would have believed it to be
homework.


Cheers & hth.,


- Alf

Juha Nieminen 07-18-2009 08:01 PM

Re: Template instantiation context
 
Alf P. Steinbach wrote:
> Btw., please don't formulate real questions so that they sound like
> homework.


I don't know if you have seen me posting in this group before, but if
you have, you'd probably know that I have been in the business for long
enough that doing homework is way in the past for me by now... :)

This was a genuine question because I'm not completely sure how
template functions should work with respect to:

a) local static variables
b) variables in the outer scope

My best guess is that one type generates one single function (which,
if duplicated in more than one object file, gets merged by the linker),
in which case the static variable should be unique even when the
function is instantiated in more than one compilation unit. But that
raises the question what happens when the context is different (in this
case, when the variable name in the outer scope refers to different
variables in the two compilation units).

Rather than writing an essay as my question, I kept the post short and
simple.

Pavel 07-18-2009 10:07 PM

Re: Template instantiation context
 
Alf P. Steinbach wrote:
> * Juha Nieminen:
>> Assume we have these three files:
>>
>> //--------------------------------------------------------------
>> // foo.hh
>> #include <iostream>
>>
>> template<typename T>
>> void foo(T value)
>> {
>> static int s = 0;
>> ++s;
>> std::cout << "value:" << value << ", s:" << s
>> << ", externalVar:" << externalVar << std::endl;
>> }
>> //--------------------------------------------------------------
>>
>> //--------------------------------------------------------------
>> // bar.cc
>> namespace { const int externalVar = 456; }
>> #include "foo.hh"
>>
>> void bar()
>> {
>> std::cout << "In bar(): ";
>> foo(200);
>> }
>> //--------------------------------------------------------------
>>
>> //--------------------------------------------------------------
>> // test.cc
>> namespace { const int externalVar = 123; }
>> #include "foo.hh"
>>
>> void bar();
>>
>> int main()
>> {
>> std::cout << "In main(): ";
>> foo(100);
>> bar();
>> }
>> //--------------------------------------------------------------
>>
>> Now we compile test.cc and bar.cc into an executable program. What
>> should be the output of this program?

>
> It's UB.
>
> Btw., please don't formulate real questions so that they sound like
> homework.
>
> If this question had any other answer than UB I would have believed it
> to be homework.

Why? It could be an interview questions but then OP would not be able to
use Internet. I can't see how it could be HW. It looks like a fully
compliant question to me.

-Pavel

Bo Persson 07-18-2009 10:08 PM

Re: Template instantiation context
 
Juha Nieminen wrote:
> Alf P. Steinbach wrote:
>> Btw., please don't formulate real questions so that they sound like
>> homework.

>
> I don't know if you have seen me posting in this group before, but
> if you have, you'd probably know that I have been in the business
> for long enough that doing homework is way in the past for me by
> now... :)
>
> This was a genuine question because I'm not completely sure how
> template functions should work with respect to:
>
> a) local static variables
> b) variables in the outer scope
>
> My best guess is that one type generates one single function
> (which, if duplicated in more than one object file, gets merged by
> the linker), in which case the static variable should be unique
> even when the function is instantiated in more than one compilation
> unit. But that raises the question what happens when the context is
> different (in this case, when the variable name in the outer scope
> refers to different variables in the two compilation units).
>
> Rather than writing an essay as my question, I kept the post short
> and simple.


By having different meanings for the for the name in the outer scope,
you have violated the One Definition Rule.

A template can be defined in several translation units, but the
meaning must be the same. Here it is not.


Bo Persson



Alf P. Steinbach 07-18-2009 10:43 PM

Re: Template instantiation context
 
* Pavel:
> Alf P. Steinbach wrote:
>> * Juha Nieminen:
>>> Assume we have these three files:
>>>
>>> //--------------------------------------------------------------
>>> // foo.hh
>>> #include <iostream>
>>>
>>> template<typename T>
>>> void foo(T value)
>>> {
>>> static int s = 0;
>>> ++s;
>>> std::cout << "value:" << value << ", s:" << s
>>> << ", externalVar:" << externalVar << std::endl;
>>> }
>>> //--------------------------------------------------------------
>>>
>>> //--------------------------------------------------------------
>>> // bar.cc
>>> namespace { const int externalVar = 456; }
>>> #include "foo.hh"
>>>
>>> void bar()
>>> {
>>> std::cout << "In bar(): ";
>>> foo(200);
>>> }
>>> //--------------------------------------------------------------
>>>
>>> //--------------------------------------------------------------
>>> // test.cc
>>> namespace { const int externalVar = 123; }
>>> #include "foo.hh"
>>>
>>> void bar();
>>>
>>> int main()
>>> {
>>> std::cout << "In main(): ";
>>> foo(100);
>>> bar();
>>> }
>>> //--------------------------------------------------------------
>>>
>>> Now we compile test.cc and bar.cc into an executable program. What
>>> should be the output of this program?

>>
>> It's UB.
>>
>> Btw., please don't formulate real questions so that they sound like
>> homework.
>>
>> If this question had any other answer than UB I would have believed it
>> to be homework.

> Why? It could be an interview questions but then OP would not be able to
> use Internet. I can't see how it could be HW. It looks like a fully
> compliant question to me.


The "What should be the output of this program?" triggered my HW recognition
meter. It is the form of the question, a code example followed by "what does
this do?", which is characteristic of homework and almost never what the author
of the code in question would ask. I ignored the HW meter needle's movement
because if it was homework then there would be a definite answer, not UB. :-)


Cheers & hth.,

- Alf

Classic Wrinwright 07-19-2009 01:14 AM

Re: Template instantiation context
 
g++ -Wall -g bar.cc test.cc produces:
In main(): value:100, s:1, externalVar:456
In bar(): value:200, s:2, externalVar:456


James Kanze 07-19-2009 11:26 AM

Re: Template instantiation context
 
On Jul 18, 7:43 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * Juha Nieminen:


[...]
> > Now we compile test.cc and bar.cc into an executable
> > program. What should be the output of this program?


> It's UB.


> Btw., please don't formulate real questions so that they sound
> like homework.


> If this question had any other answer than UB I would have
> believed it to be homework.


I'd say that the author would have been enough; Juha's not
exactly new to this group. And I've not seen much homework
which involves separate compilation (or other things essential
when writing real code).

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Juha Nieminen 07-19-2009 12:00 PM

Re: Template instantiation context
 
Classic Wrinwright wrote:
> g++ -Wall -g bar.cc test.cc produces:
> In main(): value:100, s:1, externalVar:456
> In bar(): value:200, s:2, externalVar:456


Well, I didn't ask what gcc will print (because I can test that
myself). I asked what *should* be printed.

(OTOH, if the value printed for externalVar is indeed UB, then any
value would be as valid as anything else, I suppose.)

James Kanze 07-20-2009 07:45 AM

Re: Template instantiation context
 
On Jul 19, 2:00 pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> Classic Wrinwright wrote:
> > g++ -Wall -g bar.cc test.cc produces:
> > In main(): value:100, s:1, externalVar:456
> > In bar(): value:200, s:2, externalVar:456


> Well, I didn't ask what gcc will print (because I can test
> that myself).


Actually, you can't very well, since g++ doesn't define it any
more than the standard does. Thus (on my Linux box):

$ g++ -std=c++98 -pedantic bar.cc test.cc
$ a.out
In main(): value:100, s:1, externalVar:456
In bar(): value:200, s:2, externalVar:456
$ g++ -std=c++98 test.cc bar.cc
$ a.out
In main(): value:100, s:1, externalVar:123
In bar(): value:200, s:2, externalVar:123
$ g++ -std=c++98 -pedantic -O bar.cc test.cc
$ a.out
In main(): value:100, s:1, externalVar:123
In bar(): value:200, s:2, externalVar:456

So there is no correct answer to what g++ will print. (Which is
what undefined behavior is all about.)

> I asked what *should* be printed.


> (OTOH, if the value printed for externalVar is indeed UB, then
> any value would be as valid as anything else, I suppose.)


Anything the compiler does is valid. Including refusing to
compile the code. (IMHO, it wouldn't be that difficult to
detect the problem at link time, and generate an error message
then.)

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


All times are GMT. The time now is 10:17 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.