Thread overview
Getting the size of a type tuple
Sep 21, 2017
David Zhang
Sep 21, 2017
ag0aep6g
Sep 21, 2017
David Zhang
Sep 21, 2017
H. S. Teoh
Sep 21, 2017
ag0aep6g
September 21, 2017
Given the function F, where: F(Args...)(Args args) { ... }

How can I statically determine the size of the argument list in bytes?

Preferably, I would like a one-liner. However, std.algorithm doesn't seem to support tuples, or `Args.each!(T => T.sizeof).sum` would work.

For the moment, I've settled on using a helper function:

size_t size(Args...)()
{
    size_t size;
    foreach(Arg; Args)
        size += Arg.sizeof;
    return size;
}

But it's a bit clunky. Is there a more idiomatic way to do this?

Thanks
September 21, 2017
On 09/21/2017 08:44 PM, David Zhang wrote:
> Given the function F, where: F(Args...)(Args args) { ... }
> 
> How can I statically determine the size of the argument list in bytes?
> 
> Preferably, I would like a one-liner. However, std.algorithm doesn't seem to support tuples, or `Args.each!(T => T.sizeof).sum` would work.
> 
> For the moment, I've settled on using a helper function:
> 
> size_t size(Args...)()
> {
>      size_t size;
>      foreach(Arg; Args)
>          size += Arg.sizeof;
>      return size;
> }
> 
> But it's a bit clunky. Is there a more idiomatic way to do this?

I don't have a one-liner, but here are some other solutions that might be interesting. None of them is particularly pretty, though.

1) Recursive template:
----
template size_recur(Types ...)
{
    static if (Types.length == 0) enum size_recur = 0;
    else enum size_recur = Types[0].sizeof + size_recur!(Types[1 .. $]);
}
----

2) Using the std library:
----
template size_std(Types ...)
{
    import std.algorithm: sum;
    import std.range: only;
    import std.meta: staticMap;
    enum sizeOf(T) = T.sizeof;
    enum size_std = staticMap!(sizeOf, Types).only.sum;
}
----

3) Declaring a packed struct in a function literal that gets immediately called:
----
enum size_so_very_clever(Types ...) = () {
    struct S { align(1) Types fields; }
    return S.sizeof;
} ();
----
September 21, 2017
On Thursday, 21 September 2017 at 19:49:14 UTC, ag0aep6g wrote:
> I don't have a one-liner, but here are some other solutions that might be interesting. None of them is particularly pretty, though.
>
> 1) Recursive template: <snip>
>
> 2) Using the std library: <snip>
>
> 3) Declaring a packed struct in a function literal that gets immediately called: <snip>

I think the recursive one looks best, but I agree. None of them look particularly good.
September 21, 2017
On Thu, Sep 21, 2017 at 09:49:14PM +0200, ag0aep6g via Digitalmars-d-learn wrote: [...]
> 3) Declaring a packed struct in a function literal that gets immediately called:
> ----
> enum size_so_very_clever(Types ...) = () {
>     struct S { align(1) Types fields; }
>     return S.sizeof;
> } ();
> ----

I'd just do:

	template sizeofStruct(Types...) {
		struct S { align(1) Types fields; }
		enum sizeofStruct = S.sizeof;
	}

Skip the CTFE implied by the function literal, the compiler already knows the size very well.


T

-- 
What are you when you run out of Monet? Baroque.
September 21, 2017
On 09/21/2017 09:59 PM, H. S. Teoh wrote:
> On Thu, Sep 21, 2017 at 09:49:14PM +0200, ag0aep6g via Digitalmars-d-learn wrote:
> [...]
>> 3) Declaring a packed struct in a function literal that gets
>> immediately called:
>> ----
>> enum size_so_very_clever(Types ...) = () {
>>      struct S { align(1) Types fields; }
>>      return S.sizeof;
>> } ();
>> ----
> 
> I'd just do:
> 
> 	template sizeofStruct(Types...) {
> 		struct S { align(1) Types fields; }
> 		enum sizeofStruct = S.sizeof;
> 	}
> 
> Skip the CTFE implied by the function literal, the compiler already
> knows the size very well.

Yup. That's better.