struct op_f_##OPNAME { \
template <typename T, typename U> \
requires requires(T l, U r) { (OP_F)(l, r); } \
auto operator()(const T &l, const U &r) { \
return (OP_F)(l, r); \
} \
template <typename T, typename U> \
auto operator()(const T &l, const U &r) -> decltype(l) { \
ERROR("Invalid operator " #OPNAME " on given types"); \
} \
}; \
Expr ConstFold::visit(
const OPNAME &op) { \
return visitBinary( \
op, [](auto l, auto r) { return op_f_##OPNAME()(l, r); }, \
[](auto l, auto r) { return make##OPNAME(l, r); }); \
}