Hi,
 
In my ideal world, I could define my logging function like this:
[[ConditionalDiscard = IsShipping()]]
template<typename... Ts>
void LogWarn(std::string_view fmt, Ts&&... args) { /* ... */ }

I assume the function IsShipping() to be constexpr.
And the effect would be a function call completely stripped 

What about the other cases where the decision for logging based on the log level is taken at runtime?
For example, I've worked with systems where the logging level for a given sub-system of the application (or the whole application) can be changed at runtime and this helps collect more information about specific production issues. 
However, we still wanted lazy evaluation of the parameters because these logs are still disabled 99% of the time.
We used macros for our logging systems. At least I don't know a better alternative for this.

Regards,
Pavel.