On Friday, 7 March 2014 at 04:01:15 UTC, Adam D. Ruppe wrote:
BTW you know what would help this? A pragma we can attach to a
struct which makes it a very thin value type.
pragma(thin_struct)
struct A {
int a;
int foo() { return a; }
static A get() { A(10); }
}
void test() {
A a = A.get();
printf("%d", a.foo());
}
With the pragma, A would be completely indistinguishable from
int in all ways.
What do I mean?
$ dmd -release -O -inline test56 -c
Let's look at A.foo:
A.foo:
0: 55 push ebp
1: 8b ec mov ebp,esp
3: 50 push eax
4: 8b 00 mov eax,DWORD PTR [eax] ;
waste!
6: 8b e5 mov esp,ebp
8: 5d pop ebp
9: c3 ret
It is line four that bugs me: the struct is passed as a
*pointer*, but its only contents are an int, which could just
as well be passed as a value. Let's compare it to an identical
function in operation:
int identity(int a) { return a; }
00000000 <_D6test568identityFiZi>:
0: 55 push ebp
1: 8b ec mov ebp,esp
3: 83 ec 04 sub esp,0x4
6: c9 leave
7: c3 ret
lol it *still* wastes time, setting up a stack frame for
nothing. But we could just as well write asm { naked; ret; }
and it would work as expected: the argument is passed in EAX
and the return value is expected in EAX. The function doesn't
actually have to do anything.
struct A {
int a;
//int foo() { return a; }
static A get() { A(10); }
}
int foo(A a) { return a.a; }
printf("%d", a.foo());
Now it's passed by value.
Though, I needed checked arithmetic only twice: for cast from
long to int and for cast from double to long. If you expect your
number type to overflow, you probably chose wrong type.