This is the mail archive of the mailing list for the libstdc++ project. See the libstdc++ home page for more information.

[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index] [Subject Index] [Author Index] [Thread Index]

Re: Static data members in template declarations

>>>>> "Jason" == Jason Merrill <> writes:

>>>>> Mark Mitchell <> writes:

    Jason> I was discussing it on the C++ committee reflector.

And a find place it is for such a discussion.  In future, would you
mind copying me on things that stem directly from issues I have

    Jason> I assume you mean the defn to use D<T>, not S<T>.  In any

Yes.  I apologize.

    Jason> case, it's not the same, because B<int>::a can be something
    Jason> else due to a specialization of B<int>, but if S<int> is
    Jason> specialized, we don't use the template for S<T>::t anyway,
    Jason> so it's moot.

You and John both made this point, which I had anticipated, but I
should have stated so more explicitly.  Although there might be a
specialization of `B' with no `a' member, but then the program would
be ill-formed.  So, if the program is well-formed, `D<T>::a' and
`B<T>::a' must be the same thing.

I don't think this should be legal, either, but I wanted to know what
rules we think we're playing by before we go implementing things.  The
previous code in g++ that tried to implement this was just plain
buggy; it allowed *anything* to match with sometimes disastrous

    >> There is no `a' in `S<T>' proper, so if `S<T>::a' is going to
    >> make sense at all, it must be because it is in fact `B<T>::a'.
    >> Is the compiler supposed to figure this out though?  What if
    >> the last line says just plain `a', not `S<T>::a'?

    Jason> Ill-formed, since 'a' is not used in a dependent context.

Good.  That's what I think too.  

I'm now switching to quoting John, not Jason.  

    John> Within a class template (such as B above) "a" can be
    John> referred to as simply "a", as "B::a", or as "B<T>::a".  When
    John> you define "t" later, you can use any one of these
    John> equivalent forms within the class and any of the equivalent
    John> forms in the definition later (assuming the form is
    John> semantically valid at that point later).

    John> Does this sound like a sensible direction to you?

I think this is an internally consistent point of view, and reasonable
to implement.  

As a programmer, I don't actually mind having to use the same form in
the various places.  In some sense, it's analagous to the ODR, which
actually talks about token sequences.  This is much more restrictive
than actually necessary in that, for example,

  inline void f() { }
  iniine void f() { return; }

mean exactly the same thing.  On the other hand, token sequences are a
convenient place to draw the line.  I'm a little afraid that
programmers will start to expect more and more complex "equivalent"
forms of template declarations to match.  For example, at least some
people I mentioned this to thought that:

  template <class T> 
  struct S {
    T f(T);

  template <class T>
  int S<T>::f(T) { return 0; }

should be legal *provided you only ever instantiate `S' with `int'*.
I don't agree, and I don't think many of us would.  My point is only
that requiring the things to match *exactly* is simplest, and is a
clean place to draw the line.

The upshot: I think your proposal is reasonable, I'm just not sure the
additional complexity is necessary.  Definitive clarification of this
issue, however, is probably more important than which particular
clarification we choose.

Mark Mitchell
Mark Mitchell Consulting