Thread overview
Re: Where are the template members?
Dec 05, 2012
Simen Kjaeraas
Dec 05, 2012
Timon Gehr
Dec 05, 2012
Simen Kjaeraas
Dec 05, 2012
Gor Gyolchanyan
Dec 05, 2012
Timon Gehr
Dec 05, 2012
Gor Gyolchanyan
Dec 05, 2012
Simen Kjaeraas
Dec 05, 2012
Gor Gyolchanyan
December 05, 2012
On 2012-39-05 09:12, Gor Gyolchanyan <gor.f.gyolchanyan@gmail.com> wrote:

> Consider this piece of code:
>
> struct Test
> {
> template member(Type)
> {
> Type member;
> }
> }
>
> unittest
> {
> Test test;
> test.member!int = 0;
> test.member!long = 0;
> test.member!short = 0;
> import std.stdio; writeln(test.sizeof);
> assert(test.sizeof == int.sizeof + long.sizeof + short.sizeof); // fails
> assert(test.sizeof == 1); // succeeds
> }
>
> I don't get why the structure's size remains unchanged even after
> instantiating 3 members inside it.
> How can I get the real size of the structure, including all its members
> (template or not)?

You have. Its real size is 1, and the template instantiations are not member
fields.

A template (not a templated function [actually, sorta, but that's a different
discussion]) is basically static - if you try instead Test.member!int, you
will see that this works perfectly.

What we see here is another example of the confusion that can be caused by
static names being accessible through an instance:

struct Foo {
    static int n;
}

Foo f;

f.n = 4;

-- 
Simen
December 05, 2012
But why aren't they non-static members? If they were non-static members the
structure's size would still be compile-time, computed by the sum of sizes
of all template instances. the .sizeof would work perfectly well.
This would be an incredibly useful feature. Among other use cases this
would allow having a fully type-safe and very fast Variant type:

struct Variant
{
public:
TypeInfo type() @property
{
return _type;
}
 ref Type_ as(Type_)() @property
{
if(typeid(Type_) != _type)
throw new Exception("The requested static type doesn't match the available
dynamic type.");
 return _value!Type_;
}
private:
TypeInfo _type;

union
{
template _value(Type_)
{
Type_ _value;
}
}
}

Is there any good reason why this feature wouldn't be a good idea?


On Wed, Dec 5, 2012 at 12:51 PM, Simen Kjaeraas <simen.kjaras@gmail.com>wrote:

> On 2012-39-05 09:12, Gor Gyolchanyan <gor.f.gyolchanyan@gmail.com> wrote:
>
>  Consider this piece of code:
>>
>> struct Test
>> {
>> template member(Type)
>> {
>> Type member;
>> }
>> }
>>
>> unittest
>> {
>> Test test;
>> test.member!int = 0;
>> test.member!long = 0;
>> test.member!short = 0;
>> import std.stdio; writeln(test.sizeof);
>> assert(test.sizeof == int.sizeof + long.sizeof + short.sizeof); // fails
>> assert(test.sizeof == 1); // succeeds
>> }
>>
>> I don't get why the structure's size remains unchanged even after
>> instantiating 3 members inside it.
>> How can I get the real size of the structure, including all its members
>> (template or not)?
>>
>
> You have. Its real size is 1, and the template instantiations are not
> member
> fields.
>
> A template (not a templated function [actually, sorta, but that's a
> different
> discussion]) is basically static - if you try instead Test.member!int, you
> will see that this works perfectly.
>
> What we see here is another example of the confusion that can be caused by static names being accessible through an instance:
>
> struct Foo {
>     static int n;
> }
>
> Foo f;
>
> f.n = 4;
>
> --
> Simen
>



-- 
Bye,
Gor Gyolchanyan.


December 05, 2012
Sorry, that was wrong. This is right:

struct Variant
{
public:
TypeInfo type() @property
{
return _type;
}
 ref Type_ as(Type_)() @property
{
if(typeid(Type_) != _type)
throw new Exception("The requested static type doesn't match the available
dynamic type.");
 return _value!Type_;
}
 ref Variant opAssign(Type_)(Type_ value_)
{
_type = typeid(Type_);
_value!Type_ = value_;
return this;
}
private:
TypeInfo _type;

union
{
template _value(Type_)
{
Type_ _value;
}
}
}


On Wed, Dec 5, 2012 at 1:06 PM, Gor Gyolchanyan <gor.f.gyolchanyan@gmail.com
> wrote:

> But why aren't they non-static members? If they were non-static members the structure's size would still be compile-time, computed by the sum of sizes of all template instances. the .sizeof would work perfectly well. This would be an incredibly useful feature. Among other use cases this would allow having a fully type-safe and very fast Variant type:
>
> struct Variant
> {
> public:
>  TypeInfo type() @property
> {
> return _type;
> }
>  ref Type_ as(Type_)() @property
> {
> if(typeid(Type_) != _type)
>  throw new Exception("The requested static type doesn't match the
> available dynamic type.");
>  return _value!Type_;
> }
> private:
> TypeInfo _type;
>
> union
> {
> template _value(Type_)
>  {
> Type_ _value;
> }
> }
> }
>
> Is there any good reason why this feature wouldn't be a good idea?
>
>
> On Wed, Dec 5, 2012 at 12:51 PM, Simen Kjaeraas <simen.kjaras@gmail.com>wrote:
>
>> On 2012-39-05 09:12, Gor Gyolchanyan <gor.f.gyolchanyan@gmail.com> wrote:
>>
>>  Consider this piece of code:
>>>
>>> struct Test
>>> {
>>> template member(Type)
>>> {
>>> Type member;
>>> }
>>> }
>>>
>>> unittest
>>> {
>>> Test test;
>>> test.member!int = 0;
>>> test.member!long = 0;
>>> test.member!short = 0;
>>> import std.stdio; writeln(test.sizeof);
>>> assert(test.sizeof == int.sizeof + long.sizeof + short.sizeof); // fails
>>> assert(test.sizeof == 1); // succeeds
>>> }
>>>
>>> I don't get why the structure's size remains unchanged even after
>>> instantiating 3 members inside it.
>>> How can I get the real size of the structure, including all its members
>>> (template or not)?
>>>
>>
>> You have. Its real size is 1, and the template instantiations are not
>> member
>> fields.
>>
>> A template (not a templated function [actually, sorta, but that's a
>> different
>> discussion]) is basically static - if you try instead Test.member!int, you
>> will see that this works perfectly.
>>
>> What we see here is another example of the confusion that can be caused by static names being accessible through an instance:
>>
>> struct Foo {
>>     static int n;
>> }
>>
>> Foo f;
>>
>> f.n = 4;
>>
>> --
>> Simen
>>
>
>
>
> --
> Bye,
> Gor Gyolchanyan.
>



-- 
Bye,
Gor Gyolchanyan.


December 05, 2012
On 12/05/2012 09:51 AM, Simen Kjaeraas wrote:
> On 2012-39-05 09:12, Gor Gyolchanyan <gor.f.gyolchanyan@gmail.com> wrote:
>
>> Consider this piece of code:
>>
>> struct Test
>> {
>>     template member(Type)
>>     {
>>         Type member;
>>     }
>> }
>>
>> unittest
>> {
>> Test test;
>> test.member!int = 0;
>> test.member!long = 0;
>> test.member!short = 0;
>> import std.stdio; writeln(test.sizeof);
>> assert(test.sizeof == int.sizeof + long.sizeof + short.sizeof); // fails
>> assert(test.sizeof == 1); // succeeds
>> }
>>
>> I don't get why the structure's size remains unchanged even after
>> instantiating 3 members inside it.
>> How can I get the real size of the structure, including all its members
>> (template or not)?
>
> You have. Its real size is 1, and the template instantiations are not
> member
> fields.
>
> A template (not a templated function [actually, sorta, but that's a
> different
> discussion]) is basically static - if you try instead Test.member!int, you
> will see that this works perfectly.
>
> What we see here is another example of the confusion that can be caused by
> static names being accessible through an instance:
>
> struct Foo {
>      static int n;
> }
>
> Foo f;
>
> f.n = 4;
>
> --
> Simen

The confusion is caused by implicitly marking fields static during template instantiation instead of failing compilation.
December 05, 2012
On 12/05/2012 10:06 AM, Gor Gyolchanyan wrote:
> ...
>
> Is there any good reason why this feature wouldn't be a good idea?
> ...

Determining the size of a struct instance would require knowledge about all the code that uses the struct declaration.
December 05, 2012
Aren't the template instances generated at the place of the template?
The external code would instantiate the template, adding the instance
information to the structure.
Then the sizeof would just read the set of instantiated templates.
This wouldn't require knowing about the code which instantiates the
template.
The only requirement would be to compute the size of the structure AFTER
all template instances are generated.
The only limitation would be that separate compilation passes could
generate different structures due to different template instances, but
that's not a problem, because the static templates go through the same
limitation.



On Wed, Dec 5, 2012 at 1:11 PM, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 12/05/2012 10:06 AM, Gor Gyolchanyan wrote:
>
>> ...
>>
>>
>> Is there any good reason why this feature wouldn't be a good idea? ...
>>
>
> Determining the size of a struct instance would require knowledge about all the code that uses the struct declaration.
>



-- 
Bye,
Gor Gyolchanyan.


December 05, 2012
On 2012-43-05 10:12, Gor Gyolchanyan <gor.f.gyolchanyan@gmail.com> wrote:

> Aren't the template instances generated at the place of the template?
> The external code would instantiate the template, adding the instance
> information to the structure.
> Then the sizeof would just read the set of instantiated templates.
> This wouldn't require knowing about the code which instantiates the
> template.
> The only requirement would be to compute the size of the structure AFTER
> all template instances are generated.
> The only limitation would be that separate compilation passes could
> generate different structures due to different template instances, but
> that's not a problem, because the static templates go through the same
> limitation.

How is that not a problem?

The static templates get the same mangled name, and thus dupes can be
removed by the linker. If a type has variable size, how is one to know
that size - be it for argument passing/returning purposes, array creation,
or whatever.

-- 
Simen
December 05, 2012
On 2012-09-05 10:12, Timon Gehr <timon.gehr@gmx.ch> wrote:

> The confusion is caused by implicitly marking fields static during template instantiation instead of failing compilation.

That is certainly a valid complaint.

-- 
Simen