www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting the size of a type tuple

reply David Zhang <straivers98 gmail.com> writes:
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
Sep 21
parent reply ag0aep6g <anonymous example.com> writes:
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; } (); ----
Sep 21
next sibling parent David Zhang <straivers98 gmail.com> writes:
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.
Sep 21
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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.
Sep 21
parent ag0aep6g <anonymous example.com> writes:
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.
Sep 21