Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You could, in principle, perform formatted output without throwing the entire type system out the window. How? Rather than pass the arguments themselves, pass them wrapped up in structures that indicate their type, e.g., struct type_wrapper {int type; void *ptr; int i; char c;}; Of course, you'd have to write your own custom version of printf, possibly deal with the mess which is va_copy, but it's doable.


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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: