Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question about definition of static template member

71 views
Skip to first unread message

DSF

unread,
Nov 6, 2014, 3:32:13 PM11/6/14
to
Hello, group!

In the string template class I've been writing, I have one data
member that is static (and constant). It is called "blank" and is
used as data for an empty string. The declaration is as follows:

template <class CH> class FString
{
...
private:
static const uint blank;
};
Where uint is a typedef for unsigned integer.

Near the end of FString.h, I have the following:

template <class CH> const uint FString<CH>::blank = 0;

I wondered if this would link without duplicate "blank" errors, it
did link.

I assume each instance of FString within a given TU will use the
same "blank".

My question is, will every translation unit (TU) including FString.h
have a separate "blank" in its data segment, or will there be just one
for the entire program?

Thanks,
DSF
"'Later' is the beginning of what's not to be."
D.S. Fiscus

Victor Bazarov

unread,
Nov 6, 2014, 3:47:10 PM11/6/14
to
I remember reading that the linker will take into consideration the fact
that they all (in all TUs that refer to that symbol *and* define it) of
the same type and are *supposed to be* the same object, and will keep
only one. IOW, it's not a violation of ODR to have a definition and
initialization of a static member of a class template in the header.

V
--
I do not respond to top-posted replies, please don't ask

Paavo Helde

unread,
Nov 6, 2014, 4:25:29 PM11/6/14
to
DSF <nota...@address.here> wrote in
news:pfjn5a17tkvcu9lrt...@4ax.com:
'Data segment' is not a term which comes up in the standard. Translated
to the standardese, your question is: do the static data members of a
class template have internal or external linkage?

I think this is covered by:

14/4: A template name has linkage (3.5). A non-member function template
can have internal linkage; any other template name shall have external
linkage.

3.4.6/5: a [...] static data member [...] has external linkage if the
name of the class has external linkage.

If it were not constant, then I think this means the compiler+linker have
to guarantee there is exactly one 'blank' for each different instantiated
type CH, but with const I guess the rules are a bit relaxed. In
particular, the compiler can choose to optimize it fully away so there is
no space taken in any data segment, or to collide them all together so
there is only a single 'blank' for all instantiations and all TU-s.

Cheers
Paavo


DSF

unread,
Nov 6, 2014, 11:11:40 PM11/6/14
to
Understood about the terminology, but your translation is a bit off.
True external linkage would lead to the same identifier declared in
every TU using FString.h, which would normally be a linker error. I
know C++ has a different method of handling this to allow:
const int three = 3
To be placed in a header file in lieu of:
#define three 3
Internal linkage, I believe, would result in one "blank" per TU
using FString.h.

What I'm unclear about is if external linkage would be translated
into one single copy of "blank". Note that I don't care how many
"blank"s there are (within reason), I'm just curious as to how the
language handles this situation.

>I think this is covered by:
>
>14/4: A template name has linkage (3.5). A non-member function template
>can have internal linkage; any other template name shall have external
>linkage.
>
>3.4.6/5: a [...] static data member [...] has external linkage if the
>name of the class has external linkage.

"blank" would have external linkage. So the linker handles the
situation of multiple "blank"s with external linkage.

>If it were not constant, then I think this means the compiler+linker have
>to guarantee there is exactly one 'blank' for each different instantiated
>type CH, but with const I guess the rules are a bit relaxed. In
>particular, the compiler can choose to optimize it fully away so there is
>no space taken in any data segment, or to collide them all together so
>there is only a single 'blank' for all instantiations and all TU-s.

But shouldn't static have an effect here? The compiler should NOT
be able to optimize it fully away because it is declared static inside
a template class declaration, indicating a desire for one instance,
not internal linkage. I would think this would be a clear indication
that the programmer wants an instance of the variable and is not just
using it as an immediate value. I say "should" because I don't know
this for a fact, it just seems logical.

And even if I am wrong about the above, the template class uses a
pointer to "blank" (&blank) which, if I recall correctly, prevents the
compiler from optimizing it away.

I have an answer as it pertains to my compiler. I set a breakpoint
where "blank" is used in a program with many TUs using FString.
Regardless of the calling point, "blank" always was at the same
address.

Paavo Helde

unread,
Nov 7, 2014, 12:51:23 AM11/7/14
to
DSF <nota...@address.here> wrote in
news:v1ao5ah59qt3vui8r...@4ax.com:

> Understood about the terminology, but your translation is a bit off.
> True external linkage would lead to the same identifier declared in
> every TU using FString.h, which would normally be a linker error.

There are special provisions for templates which effectively say these
linker errors must not occur (except for fully-specialized templates,
which are essentially not templates any more).

> I
> know C++ has a different method of handling this to allow:
> const int three = 3
> To be placed in a header file in lieu of:
> #define three 3
> Internal linkage, I believe, would result in one "blank" per TU
> using FString.h.

This rule is for top-level (namespace scope) const variables, this is not
the case here.

> But shouldn't static have an effect here? The compiler should NOT
> be able to optimize it fully away because it is declared static inside
> a template class declaration, indicating a desire for one instance,
> not internal linkage.

Maybe you are right. As it is not of internal linkage, it can be
potentially observed in other TU-s and so cannot be completely optimized
away.

> And even if I am wrong about the above, the template class uses a
> pointer to "blank" (&blank) which, if I recall correctly, prevents the
> compiler from optimizing it away.

True.

> I have an answer as it pertains to my compiler. I set a breakpoint
> where "blank" is used in a program with many TUs using FString.
> Regardless of the calling point, "blank" always was at the same
> address.

That's how it must behave as far as I understand, for the same CH type.

I am more interested in about the rules for different template
instantiations. The 'blank' has the same type in all instantiations, so
it is conceivable only one of them is created even if its/their address
is taken. My compiler (MSVC2012) creates exemplars with different
addresses for each template instantiation (different CH) for non-const
'blank', but a single merged object for const 'blank'. I am not sure if
the latter is standard-conforming. Indeed, another compiler (gcc) keeps
them separate in both const and non-const cases.

Cheers
Paavo

DSF

unread,
Nov 7, 2014, 3:04:35 PM11/7/14
to
On Thu, 06 Nov 2014 23:51:09 -0600, Paavo Helde
<myfir...@osa.pri.ee> wrote:

>DSF <nota...@address.here> wrote in
>news:v1ao5ah59qt3vui8r...@4ax.com:
>
>> Understood about the terminology, but your translation is a bit off.
>> True external linkage would lead to the same identifier declared in
>> every TU using FString.h, which would normally be a linker error.
>
>There are special provisions for templates which effectively say these
>linker errors must not occur (except for fully-specialized templates,
>which are essentially not templates any more).
>
>> I
>> know C++ has a different method of handling this to allow:
>> const int three = 3
>> To be placed in a header file in lieu of:
>> #define three 3
>> Internal linkage, I believe, would result in one "blank" per TU
>> using FString.h.
>
>This rule is for top-level (namespace scope) const variables, this is not
>the case here.

I understand.

>
>> But shouldn't static have an effect here? The compiler should NOT
>> be able to optimize it fully away because it is declared static inside
>> a template class declaration, indicating a desire for one instance,
>> not internal linkage.
>
>Maybe you are right. As it is not of internal linkage, it can be
>potentially observed in other TU-s and so cannot be completely optimized
>away.
>
>> And even if I am wrong about the above, the template class uses a
>> pointer to "blank" (&blank) which, if I recall correctly, prevents the
>> compiler from optimizing it away.
>
>True.
>
>> I have an answer as it pertains to my compiler. I set a breakpoint
>> where "blank" is used in a program with many TUs using FString.
>> Regardless of the calling point, "blank" always was at the same
>> address.
>
>That's how it must behave as far as I understand, for the same CH type.
>
>I am more interested in about the rules for different template
>instantiations. The 'blank' has the same type in all instantiations, so
>it is conceivable only one of them is created even if its/their address
>is taken. My compiler (MSVC2012) creates exemplars with different
>addresses for each template instantiation (different CH) for non-const
>'blank', but a single merged object for const 'blank'. I am not sure if
>the latter is standard-conforming. Indeed, another compiler (gcc) keeps
>them separate in both const and non-const cases.

Does MSVC2012 create duplicate "blank"s for each instance even if
they are in the same TU? I would think that would be erroneous if
your 'blank' is declared static. Come to think of it, there should be
only one 'blank' for every instance of the class, even across TUs, as
long as your template class, and therefore 'blank', have external
linkage.

I think I understand MS's reasoning here in regard to const. Without
const, 'blank' may be changed per instance (or perhaps per TU,
depending on your answer to the above question regarding static). If
'blank' is always the same type, always initialized to the same value,
and const, then there is no reason to have more than one instance of
'blank' as 'blank' must contain the same value for the duration of the
program.

>Cheers
>Paavo

Thanks,

Paavo Helde

unread,
Nov 7, 2014, 5:09:43 PM11/7/14
to
DSF <nota...@address.here> wrote in
news:128q5al8num3hkhci...@4ax.com:

> Does MSVC2012 create duplicate "blank"s for each instance even if
> they are in the same TU? I would think that would be erroneous if
> your 'blank' is declared static. Come to think of it, there should be
> only one 'blank' for every instance of the class, even across TUs, as
> long as your template class, and therefore 'blank', have external
> linkage.

No, it does not create a separate 'blank' for each instance of the class
(i.e. object). It does create a separate 'blank' for each different
instantiation of the class template if 'blank' is not const (as it should
do).

> I think I understand MS's reasoning here in regard to const. Without
> const, 'blank' may be changed per instance (or perhaps per TU,
> depending on your answer to the above question regarding static). If
> 'blank' is always the same type, always initialized to the same value,
> and const, then there is no reason to have more than one instance of
> 'blank' as 'blank' must contain the same value for the duration of the
> program.

If its address is not taken, then I agree with you. But if the address of
the static member is taken, then I think different template
instantiations should have static members with different addresses. After
instantiation, these are actually totally different classes which have no
relation to each other, so why should some static data member of them to
be located at the same address?

And of course, with shared libraries and dynamic linking it is pretty
hard to know in advance if some code will take an address of some
variable or not.

Cheers
Paavo

Vir Campestris

unread,
Nov 8, 2014, 4:52:51 PM11/8/14
to
On 06/11/2014 21:25, Paavo Helde wrote:
> In
> particular, the compiler can choose to optimize it fully away

For an int (or similar) that's what I'd expect. I tend to use static
const... to replace #defines for exactly that reason.

If performance ever matters I'll check it still does it. But right now I
seem to be writing Java :(

Andy

Paavo Helde

unread,
Nov 9, 2014, 2:10:30 AM11/9/14
to
Vir Campestris <vir.cam...@invalid.invalid> wrote in news:
_fOdnaL7XMg6DcPJ...@brightview.co.uk:

> On 06/11/2014 21:25, Paavo Helde wrote:
>> In
>> particular, the compiler can choose to optimize it fully away
>
> For an int (or similar) that's what I'd expect. I tend to use static
> const... to replace #defines for exactly that reason.

For a static const data member, the compiler can (and in most cases
probably must) do both. It can optimize away all usages and use the
immediate value in the generated code, and it can still place the constant
also somewhere in some data segment, so that it has a consistent address,
should some other code pieces happen to take it.

Cheers
Paavo

DSF

unread,
Nov 18, 2014, 8:22:45 PM11/18/14
to
I have some other points, but what you just typed brought up an
interesting question. Is a static (non-const) member of a template
class:
A. Common to all implementations?

B. Common to implementations where "T" is the same type?

C. Exclusive to each implementation?

As far as const static members, from a language standpoint, it should
follow whichever of the above is correct. From a purely technical
standpoint since it has the lifespan of the process and cannot be
changed, it can exist in only one place. (This could be important if
the const static data are large and limited memory is available, as in
some imbedded systems.)

>And of course, with shared libraries and dynamic linking it is pretty
>hard to know in advance if some code will take an address of some
>variable or not.
>
>Cheers
>Paavo

DSF

unread,
Nov 18, 2014, 8:45:11 PM11/18/14
to
If I were replacing #defines, I'd only use const, as static (in this
case) implies memory allotted somewhere. (At least to me. I
understand that static const could be converted to an immediate value
as well as plain const.)

In the interest of efficiency, I would not want to use a compiler
that did both. With immediate values, you've incurred no overhead and

const int maxplayers = 12;

is on a par with

#define maxplayers = 12;

as far as memory usage goes. If the first statement also reserves
memory, then, on a modern system, you are using at least four bytes
for each equivalent of #define. That's why I would prefer that

const int maxplayers = 12;

would allot no memory, and

static const int maxplayers = 12;

would allot memory and place 12 there.

(Not that I have any say-so whatsoever. It just seems the logical
way to distinguish the two; for the programmer to make clear what
he/she wants.)

Wishing you relatively unfrustrating coding,

Öö Tiib

unread,
Nov 19, 2014, 2:26:37 AM11/19/14
to
On Wednesday, 19 November 2014 03:22:45 UTC+2, DSF wrote:
> I have some other points, but what you just typed brought up an
> interesting question. Is a static (non-const) member of a template
> class:
> A. Common to all implementations?
>
> B. Common to implementations where "T" is the same type?
>
> C. Exclusive to each implementation?

You use odd term "implementation". What you mean by it?
For example there is template class '::dsf::X' that has static
data member 'int m'.

If somewhere in your program you modify '::dsf::X<int>::m = 42'
and '::dsf::X<float>::m = 666' then those must be that for all
program from there on. '::dsf::X<int>' and '::dsf::X<float>' are
just like any other classes. There must be same definition for
those ... and their static members must be same for all program.

Paavo Helde

unread,
Nov 19, 2014, 3:08:46 AM11/19/14
to
DSF <nota...@address.here> wrote in
news:40rn6a1vgtdqr6ucb...@4ax.com:

> I have some other points, but what you just typed brought up an
> interesting question. Is a static (non-const) member of a template
> class:
> A. Common to all implementations?
>
> B. Common to implementations where "T" is the same type?
>
> C. Exclusive to each implementation?

Not sure what you mean by "implementation", but trying to translate:

A. Common to all instantiations of the template.

B. Common to a single instantiation of the template (with a certain type
T).

C. Exclusive to an instantiation of the template with a certain type T in
each translation unit.

(A) is physically impossible because static members may have different
types in different instantiations (and may be even absent or refer to
e.g. member function names in different specializations).

(B) is correct as template classes have external linkage.

(C) would be correct if template name would be of internal linkage.
However, internal linkage is allowed only for non-member function
templates, which obviously cannot have static data members.

Cheers
Paavo
0 new messages