Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is (void)sizeof(param) not "using" param?

I have a macro defined as follows:

#define UNREF_PARAM_1(a)
    do { \
        (void)sizeof(a); \
    } \
    while (0)

To get rid of compiler warnings. In a new project I am working on, VS2013 is suddenly complaining again about a unreferenced formal parameter.

Strangely it does work if I just use (void)param. Does anybody have a clue why it does not work when using it with (void)sizeof(param)?

like image 918
Chris Avatar asked Mar 18 '23 21:03

Chris


1 Answers

Because in sizeof(param), param is a so-called unevaluated operand and therefore not odr-used - that is, not needed at runtime.

However, (void)param does constitute a odr-use.

A cast with the notation in your code internally invokes a static_cast. [expr.static.cast]/6:

Any expression can be explicitly converted to type cv void, in which case it becomes a discarded-value expression (Clause 5).

[expr]/10:

In some contexts, an expression only appears for its side effects. Such an expression is called a discarded-value expression. The expression is evaluated and its value is discarded. […] The lvalue-to-rvalue conversion (4.1) is applied only if the expression is an lvalue of volatile-qualified type […]

[basic.def.odr]/2:

An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression thereof. A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied.

The first part of this quote specifies that sizeof(a) isn't an odr-use of a since a is an unevaluated operand1.
Clearly (void)a is potentially evaluated. And because a is certainly neither allowed to appear in a constant expression nor declared volatile, no lvalue-to-rvalue conversion is "immediately applied" and thus a is odr-used.


1) Here is a list of expressions where x is an unevaluated operand as from C++11:

  • typeid(x), where x is not a glvalue of polymorphic class type
  • sizeof(x) (and sizeof x)
  • noexcept(x)
  • decltype(x)
  • alignof(x)? alignas(x)?
like image 168
Columbo Avatar answered Mar 28 '23 14:03

Columbo