IssueRaiser

You're absolutely right of course; just about any facility's shortcomings can be overcome by redesigning that facility, but that's how we...

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&#x2F;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]) { &#x2F;&#x2F; 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"); &#x2F;&#x2F; 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.

Posted by sjolsen on Mar 2, 2015, 9:02 AM

Tags

Related issues

Raise real-world problems, find people facing the same issue, and discuss solutions.7,500 issues0 comments

hackernews (EdTech)

You're absolutely right of course; just about any facility's shortcomings can be overcome by redesigning that facility, but that's how we...

sjolsenMar 2, 2015, 9:02 AM

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&#x2F;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]) { &#x2F;&#x2F; 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"); &#x2F;&#x2F; 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.

Comments (0)

No comments yet. Start the discussion.

Comment on this issue