Sign in to follow this  
KingofNoobs

R-value and L-value confusion

Recommended Posts

KingofNoobs    305
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

Share this post


Link to post
Share on other sites
Brother Bob    10344
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.
[code]
mContext->PSSetShaderResources( 0, 1, i->first->GetTexture());
[/code]
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 [i]mContext[/i] object is done with it.

Share this post


Link to post
Share on other sites
KingofNoobs    305
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?

Share this post


Link to post
Share on other sites
Brother Bob    10344
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]i->first[/i] to the DX renderer instead of casting the return value from the basic renderer.
[code]
mContext->PSSetShaderResources( 0, 1, static_cast<DXRenderer *>(i->first)->GetTexture());
[/code]
I assume you have a [i]BasicRenderer[/i] class that has a [i]GetTexture[/i] function that returns a [i]BasicTexture[/i], and both of the [i]Basic[/i]-classes are derived with specific DX and GL variants. The above assumes that the renderer is a [i]DXRenderer[/i] where you have a [i]GetTexture[/i] that returns the proper type for [i]PSSetShaderResource[/i].

Share this post


Link to post
Share on other sites
Beem    127
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this