Eager instantiation of static data member

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Eager instantiation of static data member

Bakhvalov, Denis via cfe-dev
I'm puzzled why Clang (up through recent trunk) rejects

> $ cat test.cc
> template<typename T> struct S { static const int n = T::n; };
> S<int> s;
>
> $ clang++ -std=c++17 -c test.cc
> test.cc:1:54: error: type 'int' cannot be used prior to '::' because it has no members
> template<typename T> struct S { static const int n = T::n; };
>                                                      ^
> test.cc:2:8: note: in instantiation of template class 'S<int>' requested here
> S<int> s;
>        ^
> 1 error generated.

when C++17 [temp.inst]/3 states that "the initialization (and any
associated side effects) of a static data member does not occur unless
the static data member is itself used in a way that requires the
definition of the static data member to exist."

Is the initializer instantiated to check whether it is a constant
expression (as required by [class.static.data]/3)?  If yes, is the
compiler indeed allowed/required to check that when instantiating S<int>
here?

(A similar

> template<typename T> struct S { static constexpr int n = T::n; };
> S<int> s;

is accepted by Clang, FWIW.)
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Eager instantiation of static data member

Bakhvalov, Denis via cfe-dev
On 04/01/2019 11:17, Stephan Bergmann wrote:

> I'm puzzled why Clang (up through recent trunk) rejects
>
>> $ cat test.cc
>> template<typename T> struct S { static const int n = T::n; };
>> S<int> s;
>>
>> $ clang++ -std=c++17 -c test.cc
>> test.cc:1:54: error: type 'int' cannot be used prior to '::' because
>> it has no members
>> template<typename T> struct S { static const int n = T::n; };
>>                                                      ^
>> test.cc:2:8: note: in instantiation of template class 'S<int>'
>> requested here
>> S<int> s;
>>        ^
>> 1 error generated.
>
> when C++17 [temp.inst]/3 states that "the initialization (and any
> associated side effects) of a static data member does not occur unless
> the static data member is itself used in a way that requires the
> definition of the static data member to exist."
>
> Is the initializer instantiated to check whether it is a constant
> expression (as required by [class.static.data]/3)?  If yes, is the
> compiler indeed allowed/required to check that when instantiating S<int>
> here?
>
> (A similar
>
>> template<typename T> struct S { static constexpr int n = T::n; };
>> S<int> s;
>
> is accepted by Clang, FWIW.)

Upon closer inspection,

   static const int n = T::n;

is a declaration but not a definition, so C++17 [temp.inst]/2 "The
implicit instantiation of a class template specialization causes the
implicit instantiation of the declarations, but not of the definitions
[...] of the [...] static data members [...]" arguably doesn't kick in
to avoid instantiation of the initializer.  (Whereas the implicitly inline

   static constexpr int n = T::n;

/is/ a definition.)

While for the initializers of non-static data members the intent is
apparently to not instantiate them eagerly (see
<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1396>
"Deferred instantiation and checking of non-static data member
initializers", and

> template<typename T> struct S { int n = T::n; };
> S<int> s{0};

is indeed accepted by Clang), this appears to not carry over to
initializers of (non-inline, in-class) static data member declarations.

The resulting question is whether that is a conscious decision or an
oversight in the standard.  (Note that at least recent GCC appears to
not eagerly instantiate such initializers; it accepts the original test.cc.)
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev