Will a "variableName;" C++ statement be a no-op at all times?
c++, compiler-warnings
Solution
Yes, but you'll likely get another warning.
The standard way of doing this is: `(void)iid;`.
Very technically, this could still load `iid` into a register and do nothing. Granted that's extremely stupid on the compilers part (I doubt any would ever do that, if it does delete the compiler), but it's a more serious issue if the expression to be ignored is something concerning observable behavior, like calls to IO functions or the reading and writing of `volatile` variables.
This brings up an interesting question: Can we take an expression and completely ignore it?
That is, what we have now is this:
#define USE(x) (void)(x)
// use iid in an expression to get rid of warning, but have no observable effect
USE(iid);
// hm, result of expression is gone but expression is still evaluated
USE(std::cout << "hmmm" << std::endl);
This is close to a solution:
// sizeof doesn't evaluate the expression
#define USE(x) (void)(sizeof(x))
But fails with:
void foo();
// oops, cannot take sizeof void
USE(foo());
The solution is to simply:
// use expression as sub-expression,
// then make type of full expression int, discard result
#define USE(x) (void)(sizeof((x), 0))
Which guarantees no operation.
Edit: The above indeed guaranteed no effect, but I posted without testing. Upon testing, it generates a warning again, at least in MSVC 2010, because the value isn't used. That's no good, time for more tricks!
Reminder: We want to "use" an expression without evaluating it. How can this be done? Like this:
#define USE(x) ((void)(true ? 0 : (x)))
This has a simple problem like last time (worse actually), in that `(x)` needs to be be convertible to `int`. This is, again, trivial to fix:
#define USE(x) ((void)(true ? 0 : ((x), 0)))
And we're back to same kind of effect we had last time (none), but this time `x` is "used" so we don't get any warnings. Done, right?
There is actually still one problem with this solution (and was present in the last un-solution as well, but went unnoticed), and it comes up in this example:
struct foo {};
void operator,(const foo&, int) {}
foo f;
USE(f); // oops, void isn't convertible to int!
That is, if the type of the expression `(x)` overloads the comma operator to something not convertible to `int`, the solution fails. Sure, unlikely, but for the sake of going completely overboard, we can fix it with:
#define USE(x) ((void)(true ? 0 : ((x), void(), 0)))
To make sure we really end up with zero. This trick brought to you by Johannes.
Also as noted, if the above wasn't enough, a stupid enough compiler could potentially "load" the expression `0` (into a register or something), then disregard it.
I think it's impossible to be rid of that, since we ultimately need an expression to result in a type of some sort to ignore, but if I ever think of it I'll add it.
Problem
In C++ sometimes a variable will be defined, but not used. Here's an example - a function for use with `COM_INTERFACE_ENTRY_FUNC_BLIND` ATL macro: ``` HRESULT WINAPI blindQuery( void* /*currentObject*/, REFIID iid, void** ppv, DWORD_PTR /*param*/ ) { DEBUG_LOG( __FUNCTION__ ); //DEBUG_LOG macro expands to an empty string in non-debug DEBUG_LOG( iid ); iid; // <<<<<<<----silence compiler warning if( ppv == 0 ) { return E_POINTER; } *ppv = 0; return E_NOINTERFACE; } ``` In the above example `iid` parameter is used with `DEBUG_LOG` macro that expands into an empty string in non-debug configurations. So commenting out or removing the `iid` variable name in the signature is not an option. When non-debug configurations are being compiled the compiler spawns a `C4100: 'iid' : unreferenced formal parameter` warning, so in order to silence the warning the `iid;` statement that is believed to be a no-op is added. The question is the following: if we have any of the following declarations: ``` CSomeType variableName; //or CSomeType& variableName; //or CSomeType* variableName; ``` will the following statement in C++ code: ``` variableName; ``` be a no-op at all times independent of what `CSomeType` is?