R-value and L-value confusion

Started by
5 comments, last by Beem 11 years, 5 months ago
Hello all,

I do not understand why the following example 1) compiles while example 2) does not, with the noted compiler error (using VS2012).

1) ID3D11ShaderResourceView* temp = (ID3D11ShaderResourceView*) i->first->GetTexture();
mContext->PSSetShaderResources( 0, 1, (ID3D11ShaderResourceView*const*) &temp );

- OK. Compiles fine.

2) mContext->PSSetShaderResources( 0, 1, (ID3D11ShaderResourceView*const*) &(ID3D11ShaderResourceView*) (i->first->GetTexture()) );

- Not OK. The following error is generated: error C2102: '&' requires l-value

I tried researching l-values versus r-values, but it seems to me that the void* returned by GetTexture (which is actually an ID3D11ShaderResourceView) is a valid l-value. Can someone exaplain why this is not so? Originally the return value was const void * const, but I took away the const-ness in all possible combinations and this did not yield me an l-value. I know I can just use my temp hack here, but I want to know why this doesn't work to save myself coding time in the future.

Thanks in advance for all your help.

-Dave Ottley

I wonder as I wander...

http://www.davesgameoflife.com

Advertisement
The return value of a function is an l-value if an only if it is a reference type. Your pointer return type is not a reference and thus is not an l-value.
So, then what I really need to do is return a reference to a pointer with GetTexture()? If I use my temp hack, will I get unexpected results?

I wonder as I wander...

http://www.davesgameoflife.com

If this is your own code, why isn't it designed such that you can pass the return value directly into the desired function without any casts or temporary variables in the first place? You called it a "hack" yourself, and you shouldn't be hacking your own code.

mContext->PSSetShaderResources( 0, 1, i->first->GetTexture());

Whether your temporary variable is dangerous or not depends on what the receiving function assumes and expects from it. For example, if it is only assumed to live for the duration of the function call then you're fine, but if it stores the pointer locally then your temporary variable may be destroyed before your mContext object is done with it.
Brother Bob,

Thank you for your response. Yes, the function only assumes that the pointer is valid for the life of the function, so I should be ok there. The reason that I don't send the texture as the correct class is that I am attempting to make a multiplatform rendering engine (i.e. DX and GL) so having pointers to D3D types in my generic SpriteInstance class is a no-no. However, I assume that GL will also have the concept of textures and that pointers are (or can be) used to describe them, so using a void* seemed apt as it allows the client code (i.e. Graphics Subsystem) to handle the pointer as it sees fit. The pointer was originally created by the same Graphics Subsystem so there will never be a type mismatch. Does this make sense, and would you recommend coding in another way?

I wonder as I wander...

http://www.davesgameoflife.com

Do you require runtime-dynamic renderer selection? If not, then you can solve this with a simple typedef instead.

But if you need runtime-dynamic renderers, then you can you can solve this by adding a function to your DX renderer that returns the proper concrete type and cast i->first to the DX renderer instead of casting the return value from the basic renderer.

mContext->PSSetShaderResources( 0, 1, static_cast<DXRenderer *>(i->first)->GetTexture());

I assume you have a BasicRenderer class that has a GetTexture function that returns a BasicTexture, and both of the Basic-classes are derived with specific DX and GL variants. The above assumes that the renderer is a DXRenderer where you have a GetTexture that returns the proper type for PSSetShaderResource.
About that generic renderer, you don't actually want to have direct3d resource laying around in plain sight, correct? It seems to me like your master list, wherever "i" is coming from, should be internal to your renderer, and it should just contain a list of poitners to direct3d resourcees, no casting necessary. Then if you do write an OpenGL renderer, it will have it's own list of OpenGL resources. If you want to use the same code for that list, use a template. The only place where a renderer needs to be generic, is in the interface, in which case you might just return a number that represents where the resource is in some master list, but only the renderer knows if the resource is D3D or OpenGL and what information it's going to send to the video card when you want to use it.

This topic is closed to new replies.

Advertisement