Hi Andrzej!
On Fri, Jun 24, 2016 at 2:43 PM, Andrzej Krzemienski
2016-06-15 17:30 GMT+02:00 Lorenzo Caminiti
: While doing so I realized that leveraging C++11 lambda functions, Boost.Contract could be re-implemented without its crazy macros that alter C++ function declaration syntax.
If I understand correctly, the change you propose moves the assertions from function declaration into function definition. If this is the case, I would say it is a step in wrong direction. Pre-/post-conditions are part of function contract and belong in function declaration.
True this a downside of the new version, but that removes the crazy macros which I consider more important in using the library than keeping contracts with function declarations. If you are willing to manually repeat the function signature, you cal leave a small function definition in header files that will just program the contracts and then calls the body. That emulates keeping contracts with function declarations to the extent they will be clearly visible from the header files that are shipped with the compiled code: ``Contracts are part of the program specification and not of its implementation (see also Specification and Implementation). However, this library uses function definitions to program the contracts so contract code appears together with the function implementation code. ...'' https://lcaminiti.github.io/boost-contract/doc/html/boost_contract/advanced_...
Also, from the example, it looks like I will have to pay for the existence of `boost::contract::old_ptr` and `boost::contract::guard` (and compiler warnings related to them) even if I disable contracts. Is that right?
Yes, you'll pay the cost of declaring a smart pointer for old_ptr that will be assigned to null in this case (no old value copy is actually done when postconditions are disable) and a contract guard that will do nothing. The library implementation code is optimized to remove all internal members, etc. so these objects are rather simple when contracts are disable, but they are still there.
I do not know what the previous macros did, but I had the impression that they were able to erase any track of contract-related objects.
Yes, the old macros where able to completely erase contract code from user code when contracts were disabled. With the new version you can do that manually if that is truly needed: https://lcaminiti.github.io/boost-contract/doc/html/boost_contract/advanced_... However, in my experience if a piece of code is very critical for performance then I don't program contracts for it (because even the cost of checking preconditions might not be acceptable). Most of the code however is not that performance-critical, I program contracts for it, and if this contract code declares an extra empty pointer and guard even when contracts are disabled that's not an issue in practice (plus I usually leave preconditions and entry invariants enabled even in code that is shipped).
Also, the way you use the return value, forces me to depart from how I normally write return statements.
While the new version is clearly more readable, it also has certain important disadvantages compared to the previous version. What more do the new version of pre/postconditions offers compared to putting two asserts at the beginning and the end of the function?
Old values, class invariants, and subcontracting (in increasing order of implementation complexity).
Preconditions are evaluated after local object's destructors. What you propose is addressing the subject from a different anle, but is not necessarily superior to the previous version.
Absolutely correct, there is a trade-off between the old and new version (I think I pointed that out in the docs even if not in a direct comparison with the old macro interface, I will do that comparison in the Release Notes section). That said, the crazy macro syntax, long compilation/preprocessing times, and cryptic compiler/preprocessor errors were major blockers for adopting the old library in real code. The new library no longer suffers from these issues so I hope it can be more widely used. I consider that a fare trade-off with respect to the cost of not having contracts in declarations and small run-time overheads associated with empty old_ptr and guard when contracts are all disabled (also programmers can manually program extra code to get around these limitations in sections of the code where they really are limiting in practice). Thanks, --Lorenzo