Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added an exception for macros and SFINAE

...

Code Block
bgColor#ccccff
languagecpp
langc
#include <iostream>

void f() {
  int i = 0;
  decltype(i) h = 12;
  ++i;
  std::cout << i;
}

Exceptions

EXP32-EX1: It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or SFINAE context. While these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects.

The following code is an example of compliant code using an unevaluated operand in a macro definition:

Code Block
bgColor#ccccff
languagecpp
langc
void small(int x);
void large(long long x);
 
#define m(x) \
  do {
    if (sizeof(x) == sizeof(int)) { \
      small(x); \
    } else if (sizeof(x) == sizeof(long long)) { \
      large(x); \
    } \
  } while (0)
 
void f() {
  int i = 0;
  m(++i);
}

The expansion of the macro m will result in the expression ++i being used as an unevaluated operand to sizeof(), however the expectation of the programmer at the expansion loci is that i is preincremented only once.

The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented:

Code Block
bgColor#ccccff
languagecpp
langc
#include <iostream>
#include <type_traits>
#include <utility>


template <typename T>
class is_incrementable {
  typedef char one[1];
  typedef char two[2];
  static one &is_incrementable_helper(decltype(std::declval<typename std::remove_cv<T>::type&>()++) *p);
  static two &is_incrementable_helper(...);
  
public:
  static const bool value = sizeof(is_incrementable_helper(nullptr)) == sizeof(one);
};

void f() {
  std::cout << std::boolalpha << is_incrementable<int>::value;
}

In an instantiation of is_incrementable, the use of the postfix increment operator generates side effects which are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are only used for SFINAE.

Risk Assessment

If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior.

...