Bug 26355 - defining static members of specialized template classes doesn't work
Summary: defining static members of specialized template classes doesn't work
Status: RESOLVED DUPLICATE of bug 22095
Alias: None
Product: gcc
Classification: Unclassified
Component: regression (show other bugs)
Version: 4.0.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2006-02-18 22:18 UTC by Vadim Zeitlin
Modified: 2006-02-19 16:50 UTC (History)
2 users (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed:


Note You need to log in before you can comment on or make changes to this bug.
Description Vadim Zeitlin 2006-02-18 22:18:41 UTC
I'm not 100% sure if this is a compiler bug or a bug in my code but I think that what I'm trying to do should be valid according to 14.7.5/4 of the C++ Standard. Please consider the following example:

% cat stsp.cpp
enum V { V1, V2, V3 };

template <V v> struct Data { static int Value; };

int Data<V1>::Value;

extern int GetIt() { return Data<V1>::Value; }

Compiling this with g++ 4.0 or 4.1 doesn't work:

% g++-4.0 -c -Wall stsp.cpp
stsp.cpp:5: error: too few template-parameter-lists
% g++-4.1 -c -Wall stsp.cpp
stsp.cpp:5: error: too few template-parameter-lists

While it works with all the previous versions (down to 2.95!).

g++4 does accept the explicit specialization of the static member if you prepend "template <>" to "Data<V1>::Value" line which, IMHO, wrong too. But it doesn't define the symbol in the object file in this case.

If this is really not allowed then it would be nice to make the error message more clear.
Comment 1 Andrew Pinski 2006-02-18 22:26:48 UTC
This is invalid code.  This is a dup of bug 22095.

The diagnostic issue is filed under PR 20118.

*** This bug has been marked as a duplicate of 22095 ***
Comment 2 Andrew Pinski 2006-02-18 22:28:47 UTC
Also see PR 11930 for more help with the issue adding template<> does not emit the variable.
Comment 3 Vadim Zeitlin 2006-02-18 22:47:43 UTC
First, thanks a lot Andrew for your lightning fast reply, this is really amazing -- and incredibly helpful!

Second, really sorry, rereading the explicit specialization section once again I see that I was indeed wrong and that "template <>" is really needed.

Third, unfortunately PR 11930 does not help with my test case:
% cat -n stsp.cpp
     1  enum V { V1, V2, V3 };
     3  template <V v> struct Data { static int Value; };
     5  template struct Data<V1>;
     7  template <> int Data<V1>::Value;
     9  int main() { return Data<V1>::Value; }
% g++-4.0 -o stsp -Wall stsp.cpp
/tmp/ccywXRfg.o: In function `main':stsp.cpp:(.text+0x1d): undefined reference to `Data<(V)0>::Value'
collect2: ld returned 1 exit status

It looks like the compiler interprets the line 7 as declaration and not definition? If I add an initializer (i.e. change the line to end with "Value = 17" or "Value(17)") then it works just fine. Unfortunately in the real code the static member is a class and, worse, a class with only default ctor so I can't use "Value()" (which would be parsed as a function declaration) to force recognizing it such.

Sorry in advance if I'm missing something again but it doesn't seem normal that no definition is emitted for the example above, does it?

Thanks again for your help!
Comment 4 Richard Biener 2006-02-19 16:38:30 UTC
You need to add an initializer to make

template <> int Data<V1>::Value;

a definition.  Otherwise it's just an explicit specialization decl.  Or
if you do not want to specialize for V1, use

template <V v> int Data<v>::Value;
Comment 5 Vadim Zeitlin 2006-02-19 16:50:32 UTC
In reply to comment 4: I do realize that adding an initializer fixes the problem. But what to do if the static member is an object of a class which only has a default ctor? E.g.

enum V { V1, V2, V3 };

struct Int { Int() : x(0) { } int x; };
template <V v> struct Data { static Int Value; };

template struct Data<V1>;
template <> Int Data<V1>::Value;

int main() { return Data<V1>::Value.x; }

How to fix this example to link?

Note that the above (with or without the explicit instantiation) is just fine for Intel and Comeau compilers (and g++ < 4 of course) but not g++ 4.