[...]
In VC9's implementation (Dinkumware), 'npos' is initialized
after the class template's definition. But so it was in VC71
(Dinkumware, too), where th same code used to compile...
That's interesting. If I understand correctly, you're saying
that the code is basically something like:
template< typename charT ... >
class basic_string
{
// ...
size_t const npos ;
// ...
} ;
template< typename charT ... >
size_t const basic_string::npos = -1 ;
without any explicit specialization of basic_string.
If so, it's an interesting case. According to §14.6.4.1, the
point of instantiation of the members of the class "immediately
follows the namespace scope declaration or definition that
refers to the specialization." So given:
struct Test
{
static std::size_t const t = std::string::npos ;
} ;
, the instantiation of the static class member (which is what
contains the initialization) doesn't occur until after the end
of Test, so at the point of declaration of Test::t, the
initializer is not visible.
Should the compiler "see" this initialization or not. Quite
frankly, I think that the standard is ambiguous in this regard.
Or rather, it clearly specifies something that isn't
implementable, so we have to guess what is really meant. The
actual words are "[...]const variables or static data members of
integral or enumeration types initialized with constant
expressions." There's actually nothing there which constrains
the requirement to "visible" initializations, and taken
literally (and ignoring template issues and such), given
something like:
struct X
{
static int const i ;
} ;
, X::i should be an integral constant expression if it was
initializations with a constant expression, even if the actual
initialization were in a completely different translation unit.
This is obviously not the intent, of course, since it makes
separate compilation impossible. But what is the intent? If it
is that the initialization must be visible at the point where
the expression is used, then your example shouldn't compile,
because the initialization isn't visible until the static data
member of the template is initialized, after the class
definition which uses it. If it is that the initialization must
be visible in the translation unit, then your code is legal.
Sounds like a defect report is in order.