C++ Logo

std-proposals

Advanced search

Re: Allow use of constants and types from not-instantiation-ed template

From: Maciej Polanski <maciejpolanski75_at_[hidden]>
Date: Wed, 22 Dec 2021 00:09:21 +0100
On 20.12.2021 00:38, Tom Honermann wrote:
> On 12/19/21 2:35 PM, Maciej Polanski via Std-Proposals wrote:
>> Hello,
>>
>> So, let's just allow use of a types and static constants from
>> not-instantiation-ed template class (if possible):
>>
>> template<typename T>
>> struct Foo{
>> constexpr static int bar = 0x01;
>> };
>> int i = Foo::bar; // Doesn't compile now, but
>> could
>> int j = Foo<class Nonexisting>::bar; // Ugly hack but works
>
> The reason this isn't allowed is because, in the absence of a template
> specialization, the presumed data member doesn't exist; even when
> declared static, Foo<int>::bar and Foo<long>::bar are different data
> members (even if not dependent). This is what allows such data members
> to be specialized in a partial or explicit template specialization:
>
> template<typename T>
> struct Foo<T*> {
> constexpr static int bar = 0x02;
> };
> template<>
> struct Foo<int> {
> constexpr static int bar = 0x03;
> };
>
> This doesn't preclude the possibility of adding a new form of
> (implicit) instantiation in which the syntax you propose triggers
> instantiation of an (obviously non-dependent) global variable of sorts
> (it wouldn't be a static data member because there would be no
> associated class). That would be rather novel and different from how
> template instantiation and specialization works.
>
> Tom.
>

Thanks for pointing me problem with partial specializations. I didn't
take into account redefining of constants.
Some solution can be storing a constants in public non template base
class, as suggested in one of answers.

I can not agree, that using pure rvalues is forcing implicit
instantiation. In my excerpt you quoted, "class Nonexisting" does not
exists, so no instantiation should be ever possible - and it still compiles.

The more convoluted example:
   HelloWorld<int, HelloWorld<void*, 0>::Hello |
HelloWorld<std::iostream, -1>::World | HelloWorld<class Nonexisting,
3141592>::Exclamation>{}.work();

produces, as seen in Compiler Explorer:
     call HelloWorld<int, 7>::work()

And this all with -O0.
So I thought that whole this constexpr is compile-time-only and runtime
keeps only final results.

Thanks,
Maciej

Received on 2021-12-21 17:09:25