Re: Multiple definition and specialization of static data member
Wu Yongwei wrote:
Greg Herlihy wrote:
Wu Yongwei wrote:
[...]
I encountered a problem in a header file like the following:
template <typename DataType>
class FMC
{
public:
static DataType Epsilon;
private:
FMC() {}
};
template <typename DataType>
DataType FMC<DataType>::Epsilon = static_cast<DataType>(0.000001);
[...]
template <>
double FMC<double>::Epsilon = static_cast<double>(0.0000000001);
[...]
This one is different, since it is a full specialization. And
the rule is different (see below).
The difference between MSVC 8 and GCC is as follows.
- MSVC 8 will accept such sequence in different translation units:
template <typename DataType>
DataType FMC<DataType>::Epsilon = static_cast<DataType>(0.000001);
template <>
double FMC<double>::Epsilon = static_cast<double>(0.0000000001);
Which it is allowed to do -- but not required: the repetition of
the second one is a multiple definition, which is undefined
behavior.
but not this specific sequence (in one translation unit):
template <typename DataType>
DataType FMC<DataType>::Epsilon = static_cast<DataType>(0.000001);
template <>
double FMC<double>::Epsilon; // declaration for specialization
template <>
double FMC<double>::Epsilon = static_cast<double>(0.0000000001);
Which is correct; the standard requires a diagnostic in this
case, because of the double definition.
- GCC, on the contrary, accept only the latter sequence, but
not the former sequence in different translation units.
In which case, it is in error, because the standard requires a
diagnostic for double definitions which appear in the same
translation unit.
According the information provided by Maxim Yegorushkin
(thanks, Maxim), C++98 3.2/5 clearly specifies the exceptions
to the one definition rule:
- There can be more than one definition of a class type, enumeration
type, inline function with external linkage, class template, non-static
function template, static data member of a class template, member
function template, or template specialization for which some template
parameters are not specified in a program provided that each definition
appears in a different translation unit, and provided the definitions
satisfy the following requirements...
So GCC is (again!) correct regarding standard conformance.
I don't see it. Where does it say that there can be more than
one definitioin of a complete specification? It allows only
mutliple definitions of a partial specialization: "template
specialization for which some template parameters are not
specified". (Note that your specialization is NOT a "definition
of [... a] static data member of a class template", but a
specialization of said data member.)
The correct solution requires that the header only contain a
declaration, not a definition. And the only way for a data
declaration at namespace scope to be a declaration is for the
declaration to contain the keyword "extern". Which g++ accepts,
but not Sun CC nor VC++. Since the standard also says
(?7.1.1/5) "The extern specifier cannot be used in the
declaration of class members or function parameters", there is
certainly an argument for their refusing it.
The current situation is that 1) there is no way to portably
declare an explicit specialization of a static data member of a
template class so that it can be used in more than one
translation unit, and 2) it's far from clear that the standard
even allows it. Of the two ways you describe, one has undefined
behavior, because of illegal multiple definitions, and the other
requires a diagnostic, because of multiple definitions in the
same translation unit. Adding extern to the definition without
an initializer avoids those problems, but it is far from clear
that it is legal.
I rather suspect that a defect report is in order.
--
James Kanze GABI Software
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]