I'm implementing MY_VERIFY macro to verify values at runtime and terminate if value is bad. Currently I use the following version of MY_VERIFY:
template <typename T>
using DecayLvalueRef =
  typename std::conditional_t<
    std::is_lvalue_reference_v<T>,
    T, typename std::decay_t<T>>;
#define MY_VERIFY(expr, ...) \
  [&](auto&& _expr) constexpr noexcept -> DecayLvalueRef<decltype(_expr)> { \
    if (!static_cast<bool>(_expr)) { \
      printf("" __VA_ARGS__); \
      printf("\n"); \
      exit(-1); \
    } \
    return std::forward<decltype(_expr)>(_expr); \
  }(expr)
The point is not only to check expr, but also return it if check is ok. And it also works for constexpr. For example:
auto* res = MY_VERIFY(impl.get_ptr(), "nullptr returned");
MY_VERIFY(sizeof(char) == 1, "Bad char size");
It works perfectly well for everything but structured bindings. :(
std::map<std::string, int> mymap;
for (const auto& [key, value] : mymap) {
  MY_VERIFY(value != 0, "Bad value for key %s", key.c_str());
doesn't compile because binding key is not captured to lambda closure.
Lambda implicit capture fails with variable declared from structured binding - here is more information.
I tried to solve problem, implementing it as a template function instead of lambda:
template <typename ResultType>
constexpr auto MY_VERIFY(ResultType&& _expr, const char* format, ...) noexcept -> DecayLvalueRef<decltype(_expr)> {
  if (!static_cast<bool>(_expr)) {
    va_list args;
    va_start(args, format);
    vprintf(format, args);
    va_end(args);
    printf("\n");
    exit(-1);
  }
  return std::forward<decltype(_expr)>(_expr);
}
but in this case values for format string are evaluated before expr check, what is bad for performance reasons:
MY_VERIFY(sizeof(char) == 1, "Error value %d", SideEffect().GetValue());
In example above SideEffect instance would be created and GetValue() invoked even when expr is true.
I couldn't find solution, which worked in C++17. Any idea?
 
    