On Aug 5, 2016, at 2:13 PM, Lorenzo Caminiti
I would like to discuss contracts and exception specifications (e.g., noexcept) specifically with respect to what Boost.Contract does.
I’m not following C++ standards development closely, but perhaps my comments may be of some use.
However, noexcept can be considered part of the function contract (namely, the contract that says the function shall not throw)
For example consider a noexcept function fclose() that is called from
I’m going to use POSIX’s close() as an example in this discussion.
a destructor without a try-catch statement (correctly so because fclose is declared noexcept). If fclose() is now allowed to throw when its preconditions fail, that will cause the destructor ~x() to throw as well?!
If passed -1 as an argument, close() will set errno = EBADF and return -1. This is documented behavior. A function that throws an exception when passed -1 (or under any other circumstance) is not the close() function from POSIX and should be given a different name (if it’s declared in the global namespace, at least).
void fclose(file& f) noexcept [[requires: f.is_open()]]
I don’t see why this should be treated differently than void fclose(file& f) noexcept { if ( ! f.is_open() ) throw failed_precondition(); The purpose of noexcept, as I understand it, is to ensure that a called function will under no circumstances throw an exception, sparing the caller the need to wrap it in try/catch. Adding a loophole that allows compiler-provided glue to throw, even when the function itself strictly speaking doesn’t, invalidates this guarantee and undermines the utility of noexcept, in my opinion. If the compiler can statically prove that the precondition is always satisfied, fine. But if not, then I’d prefer that the above code not compile unless `noexcept` is removed. Josh