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
