August 06, 2020
On Thursday, 6 August 2020 at 00:58:39 UTC, Per Nordlöw wrote:
> Is it possible to implement
>
> template maxSizeOf(T...)
> {
>     static if (T.length == 1)
>         enum size_t maxSizeOf = T[0].sizeof;
>     else
>     {
>         enum size_t firstSize = T[0].sizeof;
>         enum size_t maxSizeRest = maxSizeOf!(T[1 .. $]);
>         enum size_t maxSizeOf = firstSize >= maxSizeRest ? firstSize : maxSizeRest;
>     }
> }
>
> in a non-recursive way?

Of course. In fact, it's trivial:

------
template maxSizeOf(T...)
{
	align(1) union Impl {
		T t;
	}
	enum maxSizeOf = Impl.sizeof;
}
------

To check that this does what we expect:
------
pragma(msg, maxSizeOf!(char)); // 1LU
pragma(msg, maxSizeOf!(char, short, ubyte)); // 2LU
pragma(msg, maxSizeOf!(char, long, ubyte)); // 8LU

align(1) struct S {
	long l;
	ubyte b;
}
pragma(msg, maxSizeOf!(long, S)); // 9LU
pragma(msg, maxSizeOf!(int, ubyte[7])); // 7LU
pragma(msg, maxSizeOf!(int, ubyte[3])); // 4LU
------

Why bother with recursion and all of that fancy gobbledygook when the compiler already knows how to compute the maximum size of something? ;-)
August 06, 2020
On Thursday, 6 August 2020 at 12:51:22 UTC, H. S. Teoh wrote:
> Of course. In fact, it's trivial:
>
> ------
> template maxSizeOf(T...)
> {
> 	align(1) union Impl {
> 		T t;
> 	}
> 	enum maxSizeOf = Impl.sizeof;
> }

Clever. Thanks
August 06, 2020
On Thursday, 6 August 2020 at 12:51:22 UTC, H. S. Teoh wrote:
> Of course. In fact, it's trivial:
>
> ------
> template maxSizeOf(T...)
> {
> 	align(1) union Impl {
> 		T t;
> 	}
> 	enum maxSizeOf = Impl.sizeof;
> }

I originally copied my original version of `maxSizeOf` from `std.variant.maxSize` currently being

template maxSize(T...)
{
    static if (T.length == 1)
    {
        enum size_t maxSize = T[0].sizeof;
    }
    else
    {
        import std.algorithm.comparison : max;
        enum size_t maxSize = max(T[0].sizeof, maxSize!(T[1 .. $]));
    }
}

.

It should be updated to use this trick.

However, your solution

template maxSize(T...)
{
    align(1) union Impl { T t; }
 	enum maxSize = Impl.sizeof;
}

fails as

variable `std.variant.maxSize!(void, string).Impl.__t_field_0` variables cannot be of type `void`

because one of the instances of `maxSize` in std.variant has `void` as a member `T...`.

Do you have any simple solution to this, H. S. Teoh?
August 06, 2020
On Thursday, 6 August 2020 at 13:07:14 UTC, Per Nordlöw wrote:
> Do you have any simple solution to this, H. S. Teoh?

I also tried

template maxSize(Ts...)
{
    align(1) union Impl
    {
        // See_Also: https://forum.dlang.org/thread/wbpnncxepehgcswhuazl@forum.dlang.org?page=1
        static foreach (T; Ts)
        {
            static if (!is(T == void))
            {
                pragma(msg, T.stringof ~ " _store" ~ T.mangleof ~ ";");
                mixin(T.stringof ~ " _store" ~ T.mangleof ~ ";");
            }
        }
    }
 	enum maxSize = Impl.sizeof;
}

but that fails because of types not being defined in scope such as

Cat _storeS3std7variant17__unittest_L96_C7FNfZ3Cat;
/home/per/Work/phobos/std/variant.d-mixin-88(88,5): Error: undefined identifier `Cat`


Can somebody find a better alternative?
August 06, 2020
On Thursday, 6 August 2020 at 13:18:40 UTC, Per Nordlöw wrote:
> Can somebody find a better alternative?

Let's continue discussion  at

https://github.com/dlang/phobos/pull/7582
August 06, 2020
On Thursday, 6 August 2020 at 13:18:40 UTC, Per Nordlöw wrote:
>                 mixin(T.stringof ~ " _store" ~ T.mangleof ~

Never ever use mixin(T.stringof). Always just use mixin("T") instead.

mixin("T _store", T.mangleof /* or just idx is gonna be better */,";");

Though I doubt this is going to win a benchmark anyway getting this complicated.
August 06, 2020
On Thu, Aug 06, 2020 at 01:07:14PM +0000, Per Nordlöw via Digitalmars-d-learn wrote: [...]
> However, your solution
> 
> template maxSize(T...)
> {
>     align(1) union Impl { T t; }
>  	enum maxSize = Impl.sizeof;
> }
> 
> fails as
> 
> variable `std.variant.maxSize!(void, string).Impl.__t_field_0`
> variables cannot be of type `void`
> 
> because one of the instances of `maxSize` in std.variant has `void` as a member `T...`.

Ugh, apparently `void` is one of those nasty inconsistent things that has all sorts of ad hoc behaviour:

- void cannot be used to instantiate variables (behaves sortof like a
  bottom type);
- But in spite of that, void.sizeof == 1, rather than the expected 0. My
  guess is that this has to do with the hack to make the size of void[]
  equal to its length;
- void in void[] is a top type (but only in that context -- but its
  .sizeof is inconsistent with this);
- void is a unit type when specified as a function return type (but in
  spite of that cannot be instantiated, contrary to a true unit type,
  and this contradicts its being a top type in void[]);

IOW, void is a mishmash of ad hoc things thrown together in a way that isn't even self-consistent. A chimera of exceptions that, it would seem, always require special-casing to handle.


> Do you have any simple solution to this, H. S. Teoh?

Unfortunately, no. :-(  Why does std.variant even support storing void in the first place?!


T

-- 
People tell me that I'm paranoid, but they're just out to get me.
August 06, 2020
On 8/6/20 9:23 AM, Adam D. Ruppe wrote:
> On Thursday, 6 August 2020 at 13:18:40 UTC, Per Nordlöw wrote:
>>                 mixin(T.stringof ~ " _store" ~ T.mangleof ~
> 
> Never ever use mixin(T.stringof). Always just use mixin("T") instead.
> 
> mixin("T _store", T.mangleof /* or just idx is gonna be better */,";");
> 
> Though I doubt this is going to win a benchmark anyway getting this complicated.

Well, one *could* do:

static if(is(union { Ts t; }))

and use the union for "normal" cases.

I think the CTFE solution is cleaner. Is there a good reason to avoid it?

-Steve
August 06, 2020
On 8/6/20 4:44 AM, Per Nordlöw wrote:
> On Thursday, 6 August 2020 at 01:13:28 UTC, Ali Çehreli wrote:
>> Boring in D. :p
>>
>> template maxSizeOf(T...) {
>>   enum maxSizeOf = compute();
>>
>>   auto compute() {
>>     size_t result;
>>     static foreach (t; T) {
>>       if (t.sizeof > result) {
>>         result = t.sizeof;
>>       }
>>     }
>>     return result;
>>   }
>> }
> 
> Thanks. I'm gonna benchmark this against my templated solution.

I guess an anonymous function would remove the need for that creative name. :)

  enum maxSizeOf = {
    // ...
  }();

Ali

1 2
Next ›   Last »