I was trying to make my code less bloated when dealing with windows API by replacing two-liners not unlike
TEMP t{0,1,2}; // let's say it's struct TEMP {int a; int b; int c}
SomeVeryVerboseFunctionName(&t);
with one-liners
SomeVeryVerboseFunctionName(&TEMP{0,1,2});
but stumbled upon error:
expression must be an lvalue or function designator.
After many attempts I finally came up with code that does compile (MSVS 2013u4):
SomeVeryVerboseFunctionName(&(TEMP) TEMP{0,1,2});//explicit cast to the same type!
To better understand why the cast is needed I set up a simple test project:
#include <stdio.h>
struct A
{
int a;
int b;
A(int _a, int _b) : a(_a), b(_b) {};
};
struct B
{
int a;
int b;
};
template <typename T> void fn(T* in)
{
printf("a = %i, b = %i\n", in->a, in->b);
}
int main()
{
fn(&A{ 1, 2 }); //OK, no extra magick
/* fn(&B {3, 4}); //error: expression must be an lvalue or function designator */
fn(&(B)B{ 3, 4 }); //OK with explicit cast to B (but why?)
}
and found out that if some struct T
has an explicit constructor (like A
has in the above code), then it's possible to take address of brace-initialized temporary of type T
and pass it to a function that takes a pointer T*
, but if it doesn't have one (like B
), then the said error arises and can only be overcome by explicit casting to type T
.
So the question is: why does B
require such strange casting and A
doesn't ?
Update
Now that it's clear that treating rvalue as lvalue is an extension/feature/bug in MSVS, does anyone care to pretend it's actually a feature (enough used for MS to maintain it since 2010) and elaborate on why temporaries of A
and B
need to be passed in different ways in order to satisfy the compiler? It must have something to do with A's constructor and B's lack thereof...