Some notes of APIs that I’ve seen and disliked, followed by suggestions on how to make them, in my opinion, at least a bit better. Basically, this is a a collection of recurrent conversations that I’ve seen on code review.
Additional out parameter for signaling error
// Given bool fileContents(const String& name, String& contents); // returns bool on success to read // Usage (ignoring error) String contents; fileContents("/etc/passwd", contents); // Modifiable reference invisible without IDE support // Use the contents, but now are not const even if we don't change the file! // Usage (handling error) String contents; if (fileContents("/etc/passwd", contents)) { // Use the contents } // contents variable still in scope, but invalid
Alternative:
// Asking for the error can be optional, given the default argument. // The return value cannot be forgotten accidentally (which would make the code // a pointless function call). [[nodiscard]] String fileContents(const String& name, bool* ok = nullptr); // Usage (ignoring error) const String contents = fileContents("/etc/passwd"); // Now result can be const // Usage (handling error) bool ok = false; if (const String contents = fileContents("/etc/passwd", &ok); ok) { // Use the contents } // contents variable not in scope, but the error check one is