Error C2102: '&' requires l-value, VS2019. How to fix?
Asked Answered
G

2

5

I am using DirectX 11 and trying to load variables locally in scope using XMLoadFloat4. I am doing a lot of it and names are pretty long so I don't want to create bunch of local variables, however with code like this:

XMStoreFloat4(&vertices[0].normal, XMVector3Cross(
        XMLoadFloat4(&(vertices[2].position - vertices[0].position)),
        XMLoadFloat4(&(vertices[0].position - vertices[1].position))
        ));

I'm getting C2102. Do you know elegant way to create reference in place like this?

Greatgranduncle answered 25/12, 2020 at 0:15 Comment(8)
You're trying to pass the address of a temporary - What are you hoping to get out of it? Just store the temporary: auto a = vertices[2].position - vertices[0].position; and auto b = vertices[0].position - vertices[1].position; and then call it with &a, &b.Coexecutor
1+1 produces the value 2. Unless you put that 2 somewhere there is no address to be taken.Sprout
Since you are conformable with a lot of loads and stores, you should take a look at SimpleMath C++ wrapper for DirectXMath.Bestrew
But isn't it the local stack variable which I can take address of? Doesn't parentheses work like constructor of this local variable? So &(...) gives me the address of "..."? I wanted to avoid making local variables because they are neede only as function argument and the reason is just because DirectX doesn't make copy but takes destination address.Costplus
I also want to mention that it did work previously (on vs2017 I believe)Costplus
@MikołajGogola Apparently, MS decided to make it more close to the standard. Your code isn't strictly conformant but apparently older versions of the compiler accepted it. I have no idea if the behavior you got was defined or not. By making the code conformant (like I showed in my answer), you don't have to think about it. Any conformant compiler will treat that right.Coexecutor
@MikołajGogola Did my suggested change work?Coexecutor
Great, you're welcome!Coexecutor
C
3

Do you know elegant way to create reference in place like this?

The function expects pointers and you're trying to pass the address of temporaries which isn't allowed. Just store the temporary results in variables and pass the addresses to those:

auto a = vertices[2].position - vertices[0].position;
auto b = vertices[0].position - vertices[1].position;

XMStoreFloat4(
    &vertices[0].normal,
    XMVector3Cross(
        XMLoadFloat4(&a),
        XMLoadFloat4(&b)
    )
);
Coexecutor answered 25/12, 2020 at 0:34 Comment(2)
BTW, C2102 is a new C++ conformance warning for Visual C++ (16.8) when using /permissive-. It's worth fixing because it's not technically conformant (clang/LLVM for example would emit -Waddress-of-temporary), but you could turn off /permissive- if you didn't care.Bestrew
@ChuckWalbourn Oh, I've never tried passing the address of a temporary since isn't not conformant. Using const& to exend the lifetime of a temporary is pretty common but I'd never seen this version before.Coexecutor
M
8

You can work around this issue for now by disabling /permissive- by changing "Conformance Mode" to "No" in the C/C++ -> Language project settings.

Monah answered 3/1, 2021 at 8:29 Comment(0)
C
3

Do you know elegant way to create reference in place like this?

The function expects pointers and you're trying to pass the address of temporaries which isn't allowed. Just store the temporary results in variables and pass the addresses to those:

auto a = vertices[2].position - vertices[0].position;
auto b = vertices[0].position - vertices[1].position;

XMStoreFloat4(
    &vertices[0].normal,
    XMVector3Cross(
        XMLoadFloat4(&a),
        XMLoadFloat4(&b)
    )
);
Coexecutor answered 25/12, 2020 at 0:34 Comment(2)
BTW, C2102 is a new C++ conformance warning for Visual C++ (16.8) when using /permissive-. It's worth fixing because it's not technically conformant (clang/LLVM for example would emit -Waddress-of-temporary), but you could turn off /permissive- if you didn't care.Bestrew
@ChuckWalbourn Oh, I've never tried passing the address of a temporary since isn't not conformant. Using const& to exend the lifetime of a temporary is pretty common but I'd never seen this version before.Coexecutor

© 2022 - 2024 — McMap. All rights reserved.