From: vl106 on
{ Please confine responses to standard C++ and generic concepts of compilation
and linking, i.e. not going overboard in environment-specific discussion. -mod }

I have a question concerning the code the compiler
generates for template functions.

- why does linker not complain about ctor being there 2-times?
- does linker "strip away" compiler generated template functions (if
necessary)?
- in MSVC map file: does "i" mean: internally created by compiler?

0002:00000990 ?f_a@@YAXXZ 00411990 f a.obj
0002:000009c0 ??0?$ARRAY@H@@QAE@H@Z 004119c0 f i a.obj
0002:00000a10 ?f_b@@YAXXZ 00411a10 f b.obj

// a.cpp
#include "h.hpp"
void f_a() {
ARRAY<int> ia(3);
//...
}

// b.cpp
#include "h.hpp"
void f_b() {
ARRAY<int> ia(5);
//...
}

ARRAY is a minimalistic clone of std::vector. In a.cpp
and b.cpp I use the template class - and thus its (only)
function.

Each .obj file has a definition of ARRAY<int>::ARRAY<int>
as can be seen from assembly files (see below).

Why does linker not complain about duplicate symbols as
e.g. when I define "my_foo" both in a.cpp and b.cpp?

b.obj : error LNK2005: "void __cdecl my_foo(void)" (?my_foo@@YAXXZ)
already defined in a.obj

In the map file I recognize only

0002:000009c0 ??0?$ARRAY@H@@QAE@H@Z 004119c0 f i a.obj

that is version from b.obj is stripped away?

; in a.asm

??0?$ARRAY@H@@QAE@H@Z PROC NEAR ; ARRAY<int>::ARRAY<int>, COMDAT
; _this$ = ecx

; 15 : ARRAY<T>::ARRAY(int size) {

push ebp
mov ebp, esp
; ...
mov esp, ebp
pop ebp
ret 4
??0?$ARRAY@H@@QAE@H@Z ENDP ; ARRAY<int>::ARRAY<int>

; in b.asm

??0?$ARRAY@H@@QAE@H@Z PROC NEAR ; ARRAY<int>::ARRAY<int>, COMDAT

; _this$ = ecx

; 15 : ARRAY<T>::ARRAY(int size) {

push ebp
mov ebp, esp
; ...
mov esp, ebp
pop ebp
ret 4
??0?$ARRAY@H@@QAE@H@Z ENDP ; ARRAY<int>::ARRAY<int>


#ifndef H_HPP
#define H_HPP

template<class T>
class ARRAY {
public:
ARRAY(int size);
// further member foos
private:
T* data_;
};

template<class T>
ARRAY<T>::ARRAY(int size) {
data_ = new T[size];
}
#endif // H_HPP

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: vl106 on
"vl106" <vl106(a)hotmail.com> schrieb im Newsbeitrag
news:e60a9665-c7ef-49f4-8d31-087379969737(a)56g2000hsm.googlegroups.com...
>{ Please confine responses to standard C++ and generic concepts of
>compilation
> and linking, i.e. not going overboard in environment-specific
> discussion. -mod }
>
> I have a question concerning the code the compiler
> generates for template functions.
>
> - why does linker not complain about ctor being there 2-times?
> - does linker "strip away" compiler generated template functions (if
> necessary)?
> - in MSVC map file: does "i" mean: internally created by compiler?

Okay. I learnt that the standard requires a compiler/linker not to cause an
error.
That is new to me. For the chapters I read so far only dealt with the
language itself.
I didn't know that it also imposes requirements on the build environments.



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Alberto Ganesh Barbati on
vl106 ha scritto:
>
> I have a question concerning the code the compiler
> generates for template functions.
>
> - why does linker not complain about ctor being there 2-times?

Because the standard requires this to occur.

> - does linker "strip away" compiler generated template functions (if
> necessary)?

Probably.

> - in MSVC map file: does "i" mean: internally created by compiler?
>
> 0002:00000990 ?f_a@@YAXXZ 00411990 f a.obj
> 0002:000009c0 ??0?$ARRAY@H@@QAE@H@Z 004119c0 f i a.obj
> 0002:00000a10 ?f_b@@YAXXZ 00411a10 f b.obj

This isn't a C++ question. Wrong place to ask this.

>
> Why does linker not complain about duplicate symbols as
> e.g. when I define "my_foo" both in a.cpp and b.cpp?
>
> b.obj : error LNK2005: "void __cdecl my_foo(void)" (?my_foo@@YAXXZ)
> already defined in a.obj

You are seeing it in the wrong way. From the C++ standard point of view,
a "compiler" can be naively seen as a complex process that produce the
final executable, given the source files. The most common
implementations, for example those deriving from the C approach, split
the process in three steps: pre-processing, compilation, linking. As
these three steps are usually performed by different programs, it's
customary to call those programs pre-processor, compiler and linker, but
that's a distortion and the source of major confusion, because it
narrows the term "compiler" to one particular step, but "compiler" *is*
the whole process! There are no separate concepts as "compiler" and
"linker" in the C++ standard!

The C++ standard provides the required semantic that a compiler is
expected to implement. One required behaviour is that ODR (the One
Definition Rule) is not violated. In the case of the two definitions of
the regular function my_foo() you are violating the ODR, the program is
ill-formed and you have to get a diagnostic. In the case of a function
generated by a template instantiation, you are *not* violating the ODR
as there is still only one *definition* of the template. You may have
multiple points of instantiation for the same template but you still
have just *one* specialization of the template (see 14.6.4.1).

Now that is what the standard requires in abstract. How it's achieved in
practice, as I said, it's not relevant for standard point of view. One
possible way of implementing this, and the one you are actually seeing,
is that one specialization is actually produced in every translation
unit and then all but one of the instantiations are discarded in a
subsequent "link" step. This is not the only possibility. For example I
know there are compilers that maintain a template instantiations
database separate from the translated output of each translation unit
(aka ".obj" files).

HTH,

Ganesh

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]