3 ms·
You're absolutely right of course; just about any facility's shortcomings can be overcome by redesigning that facility, but that's how we get Greenspun's Tenth
by sjolsen 12y ago
You're absolutely right of course; just about any facility's shortcomings can be overcome by redesigning that facility, but that's how we get Greenspun's Tenth Law. :)
Unfortunately, redesigning for safety/correctness in C almost always means a loss of place-of-use conciseness. For example, you'd have to manually wrap each argument to your hypothetical printf replacement in a "struct type_wrapper." Plus, there's no way to enforce that your format string has the same number of placeholders as you have arguments.
Speaking of which, you can actually do that in C++. It would look something like
#include <cstddef>
template <std::size_t N>
static inline constexpr
std::size_t num_args (const char (&fmt) [N]) {
// Count args
}
template <std::size_t N, typename... Args>
void printf2_impl (const char* fmt, Args&&... args) {
static_assert (N == sizeof... (args), "Wrong number of arguments to printf2");
// Interleave args into fmt and print
}
#define printf2(fmt, ...) (printf2_impl <num_args (fmt)> (fmt, __VA_ARGS__))
You could even just typecheck the format string against your argument types and forward to printf. The biggest problem with this what happens when you give printf2 an empty __VA_ARGS__, but such is life when you're using the C preprocessor.