I recently received the following reader question (slightly edited):
About the (Stroustrup) approach of implementing IsDerivedFrom at page 27 in your book More Exceptional C++: […] why the second pointer assignment in:
static void Constraints(D* p)
{
B* pb=p; // okay, D better inherit from B…
pb=p; // huh? why this again?
}
Isn’t the initialization ” B* pb=p ” enough? What does the second assignment bring to the picture?
Excellent question. Interestingly, here’s the exact text from the book, which contains an additional comment that was intended to answer this specific question (emphasis added):
static void Constraints(D* p)
{
B* pb = p;
pb = p; // suppress warnings about unused variables
}
The reason for the redundant assignment is to try to shut up some compilers that issue warnings about unused variables. In a normal function, this is a helpful warning because, dollars to donuts, it’s a mistake and the programmer meant to use the variable but forgot or accidentally used some other variable instead. In this case, without the second line, pb is declared but never mentioned again, and by adding the extra line that mentions it one more time after its declaration, some compilers stop complaining.
Sometimes, however, we’re intentionally not using the variable, such as in this case where the only purpose of the function is to ensure that code that tries to convert a D* to a B* is compilable. (Note: There are other/better ways to achieve this. See the rest of Item 27 for superior approaches.)
However, in practice even the line “pb = p;” doesn’t shut compilers up very much, because many will still notice that now the second assigned value isn’t used, and will helpfully remind you that you probably didn’t mean to write an apparently useless “dead write” that is never read again. Most compilers offer a compiler-specific #pragma or other nonportable extension to silence this warning, but wouldn’t it be nice to have a portable way to suppress the warning that will work on all compilers?
Here’s a simple one-liner that works on all compilers I tried, and should not incur any overhead: Define an empty function template that takes any object by reference, but doesn’t actually do anything with it and so the empty function body should compile down to nothing. Let’s call it “ignore” – you can put it into your project namespace to avoid collisions on that common name.
template<class T> void ignore( const T& ) { }
Note that ignore<T>’s parameter does not need a name; in fact, it had better not have a name or else you’ll get the same compiler warning as before about an unused variables, only in a new place.
Using ignore is easy. When you want to suppress the compiler warning, just write:
static void Constraints(D* p)
{
B* pb = p;
ignore(pb); // portably suppresses the warning
}
Now all compilers I tried agree that the variable is “used” and stop complaining about pb.
[Oct 20: Updated to add “const” on ignore<T>’s parameter to also handle rvalues.]