This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: PR3042




--On Monday, June 11, 2001 03:29:35 PM -0400 David Edelsohn 
<dje@watson.ibm.com> wrote:

> 	Are multiple modules with
>
>   template <typename T>
>   int S<double>::i = 1;

This is not legal C++, and again that really confuses the issues.  If
we accept this code, we are broken.

Here is a brief tutorial:

  - An ordinary data member is just what C programmers call a field.
    A `static' data member is a global object, but lexically scoped
    within a class.  You could simulate these in C by prefixing
    the data member name with the name of the struct you wanted to
    associate it with.

    There are special rules for `const' static data members, so
    let's ignore them.

    A non-const static data member must be declared -- in the class
    declaration -- and defined, outside of it.  For example:

    struct S {
      static int i; // Declaration
    }

    int S::i; // Definition

    The former is equivalent to:

      extern int S__i;

    in C; the latter is equivalent to:

      int S__i;

    All the same rules about storage allocation and such hold.

  - Templates make things more complex.  Now, you have:

    template <class T> struct S {
      static int i; // Declaration
    };

    template <class T>
    int S<T>::i; // Definition

    By themselves, neither of these things allocate any storage --
    no type has been specified for T.  You have to "instantiate"
    the template.  You can do this "implicitly" by talking about
    `S<T>::i' for some choice of `T'.  For example:

      int j = S<int>::i;

    Or, you can do it "explicitly" by writing:

      template int S<int>::i;

    You are not allowed to add an initializer in the explicit
    instantiation case -- you are just asking the compiler to
    fill in the `T' and allocate storage.  If you want an
    initializer, you always add it to the lines marked `Definition'
    above.

    Because the language says you can have multiple implicit
    instantiations of the same thing, we make `S<int>::i' weak
    when implicitly instantiated.  The linker merges all the
    copies.

    The language says you can only have one explicit instantiation.
    I thought that we therefore emitted it as strong, but Jason
    implied otherwise, and he may well be right.

>
> or
>
>   template <typename T>
>   int S<T>::i = 1;
>
> allowed?  I would have thought that at least the former would produce a
> STRONG symbol in the data section.

The former is invalid C++.  The second produces no storage because
there is no instantiation.

>
> 	Both of the examples produces references but no storage allocation
> in GCC 3.0.  Without an assignment, both produce common symbols.
>
> 	Is Mark's proposal that only
>
>   template <typename T>
>   int S<double>::i;
>
> was suppose to allocate storage?

No -- that's invald C++.

My proposal was that only `template int S<double>::i;' allocate storage.
In other words, only an explicit instantiation will allocate storage,
independently of whether or not there is an initializer.  Right now,
we allocate storage for all explicit instantiations, and implicit 
instantiations of data members that do not have initializers.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]