diff --git a/doc/acknowledgments.qbk b/doc/acknowledgments.qbk index ea7b042b..5e66b11f 100644 --- a/doc/acknowledgments.qbk +++ b/doc/acknowledgments.qbk @@ -22,7 +22,7 @@ Thanks to Daniel James for his help with incorporating this library files into t Thanks to James E. King III for integrating this library with Boost's Continuous Integration (CI). -Thanks to David Maley for sharing source code form his inspiring work on emulating contract programming and subcontracting in C++ in __Maley99__. +Thanks to David Maley for sharing source code from his inspiring work on emulating contract programming and subcontracting in C++ in __Maley99__. Many thanks to Thorsten Ottosen for his work on the __N1962__ proposal (and its previous revisions) and for clarifying the proposal requirements directly with the library authors when needed. diff --git a/doc/advanced.qbk b/doc/advanced.qbk index 3ea2400a..1eaa42a8 100644 --- a/doc/advanced.qbk +++ b/doc/advanced.qbk @@ -161,7 +161,7 @@ For example (see [@../../example/features/private_protected_virtual_multi.cpp =p [warning Unfortunately, the code above does not compile on MSVC (at least up to Visual Studio 2015) because MSVC incorrectly gives a compile-time error when SFINAE fails due to private or protected access levels. -Instead, GCC and Clang correctly implement SFINAE failures due to private and protected functions so the code above correctly complies on GCC and Clang. +Instead, GCC and Clang correctly implement SFINAE failures due to private and protected functions so the code above correctly compiles on GCC and Clang. Therefore, currently it is not possible to override a function that is public in one base but private or protected in other base using this library on MSVC (at least up to Visual Studio 2015), but that can correctly be done on GCC or Clang instead. ] @@ -177,7 +177,7 @@ For example (see [@../../example/features/friend.cpp =friend.cpp=]): [friend_buffer] However, in some cases a friend function might take an object as parameter and it can be logically considered an extension of that object's public interface (essentially at the same level as the object's public functions). -In these cases, programmers might chose to program the friend function contracts using [funcref boost::contract::public_function] (instead of [funcref boost::contract::function]) so to also check the class invariants of the object passed as parameter (and not just pre- and postconditions). +In these cases, programmers might choose to program the friend function contracts using [funcref boost::contract::public_function] (instead of [funcref boost::contract::function]) so to also check the class invariants of the object passed as parameter (and not just pre- and postconditions). For example (see [@../../example/features/friend_invariant.cpp =friend_invariant.cpp=]): [footnote *Rationale:* @@ -214,7 +214,7 @@ For example: ... // Function body. } -Changing the order of the [classref boost::contract::check] declarations above, programmers can chose the order for checking class invariants among the different objects passed to the friend function and also whether to check these invariants before or after preconditions, postconditions, and exception guarantees of the friend function (see __Non_Member_Functions__ and __Public_Functions__ for information on how the RAII objects returned by [funcref boost::contract::function] and [funcref boost::contract::public_function] check contract conditions). +Changing the order of the [classref boost::contract::check] declarations above, programmers can choose the order for checking class invariants among the different objects passed to the friend function and also whether to check these invariants before or after preconditions, postconditions, and exception guarantees of the friend function (see __Non_Member_Functions__ and __Public_Functions__ for information on how the RAII objects returned by [funcref boost::contract::function] and [funcref boost::contract::public_function] check contract conditions). The example above is programmed to check `class1` invariants before `class2` invariants (but that order could have been inverted if programmers so chose). [note @@ -228,7 +228,7 @@ In the example above, preconditions are intentionally programmed to be checked b No special attention is required when using this library with overloaded functions or constructors. The only exception is for the function pointer passed to [funcref boost::contract::public_function] from public function overrides (see __Public_Function_Overrides__). -When the name of public function override are also overloaded, the related function pointer cannot be automatically deduced by the compiler so programmers have to use `static_cast` to resolve ambiguities (as usual with pointers to overloaded functions in C++). +When the name of public function override is also overloaded, the related function pointer cannot be automatically deduced by the compiler so programmers have to use `static_cast` to resolve ambiguities (as usual with pointers to overloaded functions in C++). [footnote *Rationale:* In order to avoid copies, this library takes all function arguments and the return value passed to [funcref boost::contract::public_function] as references when used within public function overrides. @@ -275,8 +275,8 @@ The library does not support contracts for functions and classes declared `const In general, it might be useful to specify contracts for `constexpr` functions and literal classes. However, the current implementation of this library cannot support contracts for `constexpr` functions and classes because C++ does not currently allow `constexpr` functions to do the following: Declare local variables of (literal) types with non-trivial `constexpr` destructors (this RAII technique is used by this library to check invariants, postconditions, and exceptions guarantees at exit); -Call other `constexpr` functions using try-catch statements (used by this library to report contract assertion failures and catch any other exception that might be thrown when evaluating the asserted conditions); -Use lambda functions (used by this library for convenience to program functors that that check preconditions, postconditions, and exception guarantees). +call other `constexpr` functions using try-catch statements (used by this library to report contract assertion failures and catch any other exception that might be thrown when evaluating the asserted conditions); +use lambda functions (used by this library for convenience to program functors that check preconditions, postconditions, and exception guarantees). Also note that even if supported, contracts for `constexpr` functions probably would not use old values (because `constexpr` prevents functions from having any side effect visible to the caller and variables recording such side-effects are usually the candidates for old value copies) and subcontracting (because `constexpr` functions cannot be virtual). ] @@ -329,7 +329,7 @@ For example, programmers can use C++11 lambda functions to define and call such } ()); `` ] -Using [macroref BOOST_CONTRACT_CHECK] is essentially equivalent to using the C-style `assert` macro a part from the following: +Using [macroref BOOST_CONTRACT_CHECK] is essentially equivalent to using the C-style `assert` macro apart from the following: * Implementation checks are disabled defining [macroref BOOST_CONTRACT_NO_CHECKS] (instead of `NDEBUG` for disabling `assert`). * If the asserted boolean condition is either false or it throws an exception then this library will call [funcref boost::contract::check_failure] (instead `assert` calls `std::abort` if the asserted condition is false and it unwinds the stack if evaluating the condition throws an exception). @@ -346,7 +346,7 @@ Specifically, there could be cases in which it makes sense to evaluate the expre This library allows to construct [classref boost::contract::old_ptr] variables using their default constructor (equivalent to a null pointer) and then to later assign them to a copy of the expression specified by [macroref BOOST_CONTRACT_OLDOF] in a nullary functor [^['d]]`()` passed to `.old(`[^['d]]`)`. The functor [^['d]]`()` is called by this library before the function body is executed but only after class invariants and preconditions are checked. -Old value assignments via `.old(...)` must appear after preconditions but before postconditions and exception guarantees wen these are all present (see __Preconditions__, __Postconditions__, and __Exception_Guarantees__). +Old value assignments via `.old(...)` must appear after preconditions but before postconditions and exception guarantees when these are all present (see __Preconditions__, __Postconditions__, and __Exception_Guarantees__). [footnote *Rationale:* Functors for preconditions, old value assignments, postconditions, and exception guarantees are all optional but when specified, they must be specified in that order. @@ -369,7 +369,7 @@ This library will automatically call the failure handler [funcref boost::contrac [note If old value pointers are initialized at the point of their construction instead of using `.old(...)` then an exception thrown by the old value expression passed to [macroref BOOST_CONTRACT_OLDOF], or more in general any exception thrown by the old value pointer initialization, will result in that exception being thrown up the stack by the enclosing function. -This is arguably less correct than calling [funcref boost::contract::old_failure] because an exception thrown by an old value copy causes the program to fail to check its postconditions and exception guarantees but should not automatically causes the enclosing function to thrown an exception (this might not be a significant difference in practice, but it could be an additional reason to use `.old(...)` instead of assigning old values when they are declared before the contract). +This is arguably less correct than calling [funcref boost::contract::old_failure] because an exception thrown by an old value copy causes the program to fail to check its postconditions and exception guarantees but should not automatically cause the enclosing function to throw an exception (this might not be a significant difference in practice, but it could be an additional reason to use `.old(...)` instead of assigning old values when they are declared before the contract). [footnote *Rationale:* It would be possible for this library to internally wrap all old value operations ([classref boost::contract::old_ptr] copy constructor, [funcref boost::contract::make_old], etc.) with try-catch statements so to call [funcref boost::contract::old_failure] also when old values are copied when they are constructed outside `.old(...)`. @@ -423,8 +423,8 @@ In general, these members must be declared `public` in the user class in order f [footnote There is some variability among compiler implementations: The `base_types` member type needs to be declared `public` on MSVC, GCC, and Clang; -The `invariant` and `static_invariant` member functions need to be declared `public` on MSVC, but not on GCC and Clang; -The `override_...` member types do not have to be declared `public` on any compiler. +the `invariant` and `static_invariant` member functions need to be declared `public` on MSVC, but not on GCC and Clang; +the `override_...` member types do not have to be declared `public` on any compiler. In any case, declaring these extra members all `public` or all `private` when the [classref boost::contract::access] class is also declared `friend` always works on all compilers. ] However, programmers might need to more precisely control the public members of their classes to prevent incorrect access of encapsulated members. @@ -483,19 +483,19 @@ For example (see [@../../example/features/throw_on_failure.cpp =throw_on_failure [import ../example/features/throw_on_failure.cpp] [throw_on_failure_handlers] -When programming custom failure handlers that trow exceptions instead of terminating the program, programmers should be wary of the following: +When programming custom failure handlers that throw exceptions instead of terminating the program, programmers should be wary of the following: * In order to comply with C++ and STL exception safety, destructors should never throw (in fact destructors are implicitly declared `noexcept` since C++11). This library passes a [enumref boost::contract::from] parameter to the contract failure handlers for preconditions, postconditions, class invariants, and old values copied at body (see [funcref boost::contract::precondition_failure], [funcref boost::contract::postcondition_failure], [funcref boost::contract::entry_invariant_failure], [funcref boost::contract::exit_invariant_failure], and [funcref boost::contract::old_failure] respectively). This [enumref boost::contract::from] parameter indicates if the contract failure occurred in a destructor, constructor, or function call so programmers can use it to code custom contract failure hander functions that never throw from destructors. (In the example above, contract failures from destructors are simply ignored even if that is probably never a safe thing to do in real production code.) -* C++ stack-unwinding will execute base class destructors even when the derived class destructor trows an exception. +* C++ stack-unwinding will execute base class destructors even when the derived class destructor throws an exception. Therefore, the contracts of base class destructors will continue to be checked when contract failure handlers are programmed to throw exceptions on contract failures from destructors (yet another reason not to throw exceptions from destructors, not even because of contract failures). * The contract failure handler for exception guarantees [funcref boost::contract::except_failure] should never throw (regardless of the value of its [enumref boost::contract::from] parameter) because when [funcref boost::contract::except_failure] is called there is already an active exception on the stack, the exception that triggered the exception guarantees to be checked in the first place (throwing an exception while there is already an active exception will force program termination or lead to undefined behaviour in C++). * Implementation checks can appear in any code, including destructor implementation code, so [funcref boost::contract::check_failure] should also never throw, or implementation checks should never be used in destructors otherwise these destructors will throw (note that [funcref boost::contract::check_failure] does not provide the [enumref boost::contract::from] parameter so it is not possible to differentiate from implementation checks failing from destructors instead than from other parts of the code). [note -Programmers need to decide how to handle contract failures from destructors when they write custom contract failure handlers that throw exceptions instead of terminating the program (given that C++ and STL exception safety rules requires destructors to never throw). +Programmers need to decide how to handle contract failures from destructors when they write custom contract failure handlers that throw exceptions instead of terminating the program (given that C++ and STL exception safety rules require destructors to never throw). This is not a simple dilemma and it might be a good reason to terminate the program instead of throwing exceptions when assertions fail in C++ (as this library and also C-style `assert` do by default). ] @@ -512,7 +512,7 @@ For example, the following precondition functor throws [classref boost::contract [throw_on_failure_ctor] [throw_on_failure_class_end] -[heading Exception Specifiers (`noexcept` and `throw``)] +[heading Exception Specifiers (`noexcept` and `throw`)] Exception specifiers `noexcept` (since C++11) and `throw` (deprecated in C++11) of the enclosing function, constructor, or destructor declaring the contract correctly apply to the contract code as well. Therefore, even if the contract failure handlers are reprogrammed to throw exceptions in case of contract failures, those exceptions will never be thrown outside the context of the enclosing operation if that is not in accordance with the exception specifiers of that operation (specifically, note that all destructors are implicitly declared `noexcept` in C++11). diff --git a/doc/contract_programming_overview.qbk b/doc/contract_programming_overview.qbk index 3d97fa21..4290ec98 100644 --- a/doc/contract_programming_overview.qbk +++ b/doc/contract_programming_overview.qbk @@ -14,7 +14,7 @@ Readers that already have a basic understanding of contract programming can skip [note The objective of this library is not to convince programmers to use contract programming. -It is assumed that programmes understand the benefits and trade-offs associated with contract programming and they have already decided to use this methodology in their code. +It is assumed that programmers understand the benefits and trade-offs associated with contract programming and they have already decided to use this methodology in their code. Then, this library aims to be the best and more complete contract programming library for C++ (without using programs and tools external to the C++ language and its preprocessor). ] @@ -31,7 +31,7 @@ This nomenclature is perfectly reasonable but it is not often used in this docum ] * /Postconditions/: These are logical conditions that programmers expect to be true when a function exits without throwing an exception (e.g., to check the result and any side effect that a function might have). Postconditions can access the function return value (for non-void functions) and also /old values/ (which are the values that expressions had before the function implementation was executed). -* /Exception guarantees/: These are logical conditions that programmers except to be true when a function exits throwing an exception. +* /Exception guarantees/: These are logical conditions that programmers expect to be true when a function exits throwing an exception. Exception guarantees can access old values (but not the function return value). [footnote *Rationale:* @@ -45,7 +45,7 @@ It is also possible to specify /static class invariants/ which are excepted to b *Rationale:* Static and volatile class invariants were first introduced by this library (simply to reflect the fact that C++ supports also static and volatile public functions), they are not part of __N1962__ or other references listed in the __Bibliography__. ] -* /Subcontracting/: This indicates that preconditions cannot be strengthen, while postconditions and class invariants cannot be weaken when a public function in a derived class overrides public functions in one or more of its base classes (this is formally defined according to the __substitution_principle__). +* /Subcontracting/: This indicates that preconditions cannot be strengthened, while postconditions and class invariants cannot be weakened when a public function in a derived class overrides public functions in one or more of its base classes (this is formally defined according to the __substitution_principle__). The actual function implementation code, that remains outside of these contract assertions, is often referred to as the /function body/ in contract programming. @@ -56,7 +56,7 @@ It is also a common requirement for contract programming to automatically disabl [note This library implements this requirement but in order to globally disable assertions while checking another assertion some kind of global arbitrating variable needs to be used by this library implementation. -This library will automatically protect such a global variable from race conditions in multi-threated programs, but this will effectively introduce a global lock in the program (the [macroref BOOST_CONTRACT_DISABLE_THREADS] macro can be defined to disable this global lock but at the risk of incurring in race conditions). +This library will automatically protect such a global variable from race conditions in multi-threaded programs, but this will effectively introduce a global lock in the program (the [macroref BOOST_CONTRACT_DISABLE_THREADS] macro can be defined to disable this global lock but at the risk of incurring in race conditions). [footnote *Rationale:* [macroref BOOST_CONTRACT_DISABLE_THREADS] is named after `BOOST_DISABLE_THREADS`. @@ -102,7 +102,7 @@ Using class invariants, programmers can describe what to expect from a class and It is the job of the constructor to ensure that the class invariants are satisfied when the object is first created. Then the implementation of the member functions can be largely simplified as they can be written knowing that the class invariants are satisfied because contract programming checks them before and after the execution of every public function. Finally, the destructor makes sure that the class invariants held for the entire life of the object checking the class invariants one last time before the object is destructed. -Class invariants can also be used as a criteria for good abstractions: If it is not possible to specify an invariant, it might be an indication that the design abstraction maybe be poor and it should not have been made into a class (maybe a namespace would have sufficed instead). +Class invariants can also be used as a criterion for good abstractions: If it is not possible to specify an invariant, it might be an indication that the design abstraction may be poor and it should not have been made into a class (maybe a namespace would have sufficed instead). * Self-documenting code: Contracts are part of the source code, they are checked at run-time so they are always up-to-date with the code itself. Therefore program specifications, as documented by the contracts, can be trusted to always be up-to-date with the implementation. @@ -131,7 +131,7 @@ This keeps the base class programmers in control as overriding functions always Contract programming assertions can replace [@http://en.wikipedia.org/wiki/Defensive_programming defensive programming] checks localizing these checks within the contracts and making the code more readable. Of course, not all formal contract specifications can be asserted in C++. -For example, in C++ is it not possible to assert the validity of an iterator range in the general case (because the only way to check if two iterators form a valid range is to keep incrementing the first iterator until it reaches the second iterator, but if the iterator range is invalid then such a code would render undefined behaviour or run forever instead of failing an assertion). +For example, in C++ it is not possible to assert the validity of an iterator range in the general case (because the only way to check if two iterators form a valid range is to keep incrementing the first iterator until it reaches the second iterator, but if the iterator range is invalid then such a code would render undefined behaviour or run forever instead of failing an assertion). Nevertheless, a large amount of contract assertions can be successfully programmed in C++ as illustrated by the numerous examples in this documentation and from the literature (for example see how much of STL [link N1962_vector_anchor `vector`] contract assertions can actually be programmed in C++ using this library). [heading Costs] @@ -139,7 +139,7 @@ Nevertheless, a large amount of contract assertions can be successfully programm In general, contract programming benefits come at the cost of performance as discussed in detail by both __Stroustrup94__ and __Meyer97__. While performance trade-offs should be carefully considered depending on the specific application domain, software quality cannot be sacrificed: It is difficult to see value in software that quickly and efficiently provides incorrect results. -The run-time performances are negatively impacted by contract programming mainly because of extra time require to: +The run-time performances are negatively impacted by contract programming mainly because of extra time required to: * Check the asserted conditions. * Copy old values when these are used in postconditions or exception guarantees. @@ -209,7 +209,7 @@ A call to the overriding public function with a contract executes the following Volatile public functions check static class invariants __AND__ volatile class invariants instead. Preconditions and postconditions of volatile public functions and volatile class invariants access the object as `volatile`. -Class invariants are checked before preconditions and postconditions so programming precondition and postcondition assertions can be simplified assuming that class invariants are satisfied already (e.g., if class invariants assert that a pointer cannot be null then preconditions and postconditions can safety dereference that pointer without additional checking). +Class invariants are checked before preconditions and postconditions so programming precondition and postcondition assertions can be simplified assuming that class invariants are satisfied already (e.g., if class invariants assert that a pointer cannot be null then preconditions and postconditions can safely dereference that pointer without additional checking). Similarly, static class invariants are checked before non-static class invariants so programming non-static class invariant (volatile and non) can be simplified assuming that static class invariants are satisfied already. Furthermore, subcontracting checks contracts of public base classes before checking the derived class contracts so programming derived class contract assertions can be simplified by assuming that public base class contracts are satisfied already. @@ -478,7 +478,7 @@ Furthermore, subcontracting preconditions is soundly defined by the __substituti [Yes.] ][ [['Constant-correctness]] - [No, enforced only for class invariants and old values (making also preconditions and postconditions constant-correct is possible but requires users to program a fare amount of boiler-plate code).] + [No, enforced only for class invariants and old values (making also preconditions and postconditions constant-correct is possible but requires users to program a fair amount of boiler-plate code).] [Yes.] [Yes (side effects in contracts lead to undefined behaviour).] [Yes.] @@ -504,7 +504,7 @@ Yes, but use [macroref BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION] to dis [footnote *Rationale:* Technically, it can be shown that an invalid argument can reach the function body when assertion checking is disabled while checking preconditions (that is why __N1962__ does not disable any assertion while checking preconditions, see [@http://lists.boost.org/Archives/boost/2010/04/164862.php Re: \[boost\] \[contract\] diff n1962]). -However, this can only happen while checking contracts when an invalid argument passed to the body, which should results in the body either throwing an exception or returning an incorrect result, will in turn fail the contract assertion being checked by the caller of the body and invoke the related contract failure handler as desired in the first place. +However, this can only happen while checking contracts when an invalid argument passed to the body, which should result in the body either throwing an exception or returning an incorrect result, will in turn fail the contract assertion being checked by the caller of the body and invoke the related contract failure handler as desired in the first place. Furthermore, not disabling assertions while checking preconditions (like __N1962__ does) makes it possible to have infinite recursion while checking preconditions. Therefore, this library by default disables assertion checking also while checking preconditions (like Eiffel does), but it also provides the [macroref BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION] configuration macro so users can change this behaviour to match __N1962__ if needed. ] diff --git a/doc/extras.qbk b/doc/extras.qbk index ea0a599d..c55621e3 100644 --- a/doc/extras.qbk +++ b/doc/extras.qbk @@ -110,7 +110,7 @@ Programmers can do this using `if constexpr` on C++17 compilers, and [funcref bo For example, let's consider the following `vector` class template equivalent to `std::vector`. C++ `std::vector` does not require that its value type parameter `T` has an equality operator `==` (it only requires `T` to be copy constructible, see `std::vector` documentation). However, the contracts for the `vector::push_back(value)` public function include a postcondition `back() == value` that introduces the new requirement that `T` must also have an equality operator `==`. -Programmers can specify this postcondition as usual with `BOOST_CONTRACT_ASSERT(back() == value)` an let the program fail to compile when users instantiate `vector` with a type `T` that does not provide an equality operator `==`. +Programmers can specify this postcondition as usual with `BOOST_CONTRACT_ASSERT(back() == value)` and let the program fail to compile when users instantiate `vector` with a type `T` that does not provide an equality operator `==`. Otherwise, programmers can guard this postcondition using C++17 `if constexpr` to evaluate the asserted condition only for types `T` that have an equality operator `==` and skip it otherwise. [footnote *Rationale:* @@ -201,7 +201,7 @@ The [funcref boost::contract::condition_if_c], [funcref boost::contract::call_if [import ../example/features/call_if_cxx14.cpp] On compilers that support C++17 `if constexpr` there should be no need to use [funcref boost::contract::condition_if] or [funcref boost::contract::call_if] because `if constexpr` can be used instead (making the code more readable and easier to program). [footnote -A part from its use within contracts, [funcref boost::contract::call_if] can be used together with C++14 generic lambdas to emulate C++17 `if constexpr` (`boost::hana::if_` and probably other approaches can also be used together with generic lambdas to emulate C++17 `if constexpr` on C++14 compilers). +Apart from its use within contracts, [funcref boost::contract::call_if] can be used together with C++14 generic lambdas to emulate C++17 `if constexpr` (`boost::hana::if_` and probably other approaches can also be used together with generic lambdas to emulate C++17 `if constexpr` on C++14 compilers). For example, the following implementation of `myadvance` will compile since C++14 and it is more concise, easier to read and maintain than the usual implementation of `std::advance` that uses tag dispatching (see [@../../example/features/call_if_cxx14.cpp =call_if_cxx14.cpp=]): [call_if_cxx14] Of course, since C++17 the implementation that uses `if constexpr` is even more readable and concise: @@ -228,7 +228,7 @@ void myadvance(Iter& i, Dist n) { This library allows to specify a different set of class invariants to check for volatile public functions. These /volatile class invariants/ are programmed in a public `const volatile` function, named `invariant`, taking no argument, and returning `void` (see [macroref BOOST_CONTRACT_INVARIANT_FUNC] to name the invariant function differently from `invariant` and __Access_Specifiers__ to not have to declare it `public`). -Classes that do no have invariants for their volatile public functions, simply do not declare the `void invariant() const volatile` function. +Classes that do no have invariants for their volatile public functions simply do not declare the `void invariant() const volatile` function. In general, `const volatile` invariants work the same as `const` invariants (see __Class_Invariants__) with the only difference that `volatile` and `const volatile` functions check `const volatile` invariants while non-`const` (i.e., neither `const` nor `volatile`) and `const` functions check `const` invariants. A given class can specify any combination of `static`, `const volatile`, and `const` invariant functions (see __Class_Invariants__): @@ -255,7 +255,7 @@ That way all public functions, `volatile` or not, will check `const volatile` in [footnote *Rationale:* Note that while all public functions can be made to check `const volatile` invariants, it is never possible to make volatile public functions check `const` non-volatile invariants. -That is because both `const` and `volatile` can always be added but never stripped in C++ (a part from forcefully via `const_cast`) but `const` is always automatically added by this library in order to enforce contract constant-correctness (see __Constant_Correctness__). +That is because both `const` and `volatile` can always be added but never stripped in C++ (apart from forcefully via `const_cast`) but `const` is always automatically added by this library in order to enforce contract constant-correctness (see __Constant_Correctness__). That said, it would be too stringent for this library to also automatically add `volatile` and require all functions to check `const volatile` (not just `const`) invariants because only `volatile` members can be accessed from `const volatile` invariants so there could be many `const` (but not `const volatile`) members that are accessible from `const` invariants but not from `const volatile` invariants. To avoid this confusion, this library has chosen to draw a clear dichotomy between `const` and `const volatile` invariants so that only volatile public functions check `const volatile` invariants and only non-volatile public functions check `const` (but not `const volatile`) invariants. This is a clear distinction and it should serve most cases. @@ -274,7 +274,7 @@ If programmers need non-volatile public functions to also check `const volatile` ... }; -(As usual, private and protected functions do not check any invariant, not even when they are `volatile` or `const volatile`, see __Private_and_Protected_Functions__). +(As usual, private and protected functions do not check any invariant, not even when they are `volatile` or `const volatile`, see __Private_and_Protected_Functions__.) [endsect] @@ -296,7 +296,7 @@ For example (see [@../../example/features/move.cpp =move.cpp=]): This example assumes that it is possible to call the public function `moved()` on the moved-from object. [footnote In this example, the `moved()` function is simple enough that programmers could decide to not even call [funcref boost::contract::public_function] from it for optimization reasons. -However, calling [funcref boost::contract::public_function] from `moved()` has no negative impact, a part from run-time overhead, because this library automatically disables contract checking while checking other contracts (so this call will not cause infinite recursion). +However, calling [funcref boost::contract::public_function] from `moved()` has no negative impact, apart from run-time overhead, because this library automatically disables contract checking while checking other contracts (so this call will not cause infinite recursion). ] [note @@ -314,7 +314,7 @@ Specifically, they might decide to not program contracts for a class that needs A C++ `union` cannot have virtual functions, base classes, and cannot be used as a base class thus subcontracting ([classref boost::contract::virtual_], [macroref BOOST_CONTRACT_OVERRIDE], etc.) do not apply to unions. Also a `union` cannot inherit from [classref boost::contract::constructor_precondition] (because it cannot have base classes), instead [classref boost::contract::constructor_precondition] is used to declare a local object that checks constructor preconditions (at the very beginning of the constructor before old value copies and other contracts, see declaration of `pre` in the example below). -A part from that, this library is used as usual to program contracts for unions. +Apart from that, this library is used as usual to program contracts for unions. For example (see [@../../example/features/union.cpp =union.cpp=]): [import ../example/features/union.cpp] @@ -350,7 +350,7 @@ Similarly, [macroref BOOST_CONTRACT_AUDITS] can be used to disable expensive old [assertion_level_class_end] The condition passed to [macroref BOOST_CONTRACT_ASSERT_AXIOM] is compiled but not actually evaluated at run-time so this macro can be used to program computationally prohibitive assertions but also assertions that cannot actually be programmed in C++ using functions that are declared but left undefined. -For example, (see [@../../example/features/assertion_level.cpp =assertion_level.cpp=]): +For example (see [@../../example/features/assertion_level.cpp =assertion_level.cpp=]): [assertion_level_no_impl] [assertion_level_class_begin] @@ -450,7 +450,7 @@ Usually, if the overhead of checking preconditions and other assertions is alrea Contracts are part of the program specifications and not of its implementation (see __Specifications_vs_Implementation__). However, this library uses function definitions to program contracts so contract code appears together with the function implementation code. -This is not ideal (even if contracts programmed using this library will always appear at the very beginning of the function definition so programmers will easily be able to distinguish contract code from the rest of the function implementation code so this might not be real limitation in practise). +This is not ideal (even if contracts programmed using this library will always appear at the very beginning of the function definition so programmers will easily be able to distinguish contract code from the rest of the function implementation code so this might not be real limitation in practice). In some cases, it might be desirable to completely separate the contract code from the function implementation code. For example, this could be necessary for software that ships only header files and compiled object files to its users. @@ -462,7 +462,7 @@ This technique allows to keep the contract code in header files while separating However, this adds the overhead of manually programming an extra function declaration for each body function (plus the limitation that constructor member initialization lists must be programmed in header files because that is where constructors need to be defined to list constructor contract code). [footnote When used as default parameter values, lambda functions allow to program code statements within function declarations. -However, these lambadas cannot be effectively used to program contracts in function declarations instead of definitions. +However, these lambdas cannot be effectively used to program contracts in function declarations instead of definitions. That is because the C++11 standard does not allow lambdas in function declarations to capture any variable (for the good reason that it is not at all obvious how to correctly define the semantics of such captures). For example, the following code is not valid C++ and it does not compile: `` @@ -515,7 +515,7 @@ When contracts are programmed only in =.cpp= files and also all this library hea Then the code in these =.cpp= files will always have such contract checking disabled even when linked to some other user code that might have been compiled with a different set of contracts disabled (i.e., a different set of `BOOST_CONTRACT_NO_...` macros defined). This technique might be useful to ship compiled object files (e.g., for a library) that will never check some contracts (e.g., postconditions, exception guarantees, and exit invariants) regardless of the definition of the `BOOST_CONTRACT_NO_...` macros used to compile code that links against the shipped object files. -On the flip side, if contracts are programmed only in header files (e.g., using extra `..._body` functions as shown in this section) and this library headers are `#include`d only in these header files that are being shipped, then end users can enable or disables contract checking of the shipped code by defining the `BOOST_CONTRACT_NO_...` macros when they compile the shipped header files as part of their code. +On the flip side, if contracts are programmed only in header files (e.g., using extra `..._body` functions as shown in this section) and this library headers are `#include`d only in these header files that are being shipped, then end users can enable or disable contract checking of the shipped code by defining the `BOOST_CONTRACT_NO_...` macros when they compile the shipped header files as part of their code. This technique might be useful in other situations when programmers that ship code want to leave it up the their end users to decide which contracts of the shipped code should be checked at run-time. ] @@ -555,7 +555,7 @@ If programmers also want to fully enforce all contract programming constant-corr * Precondition functions (i.e., the `..._precondition` functions in the example above) can take their arguments either by `const` value or by `const&`, and when they are member functions they should be either `static` or `const` functions. * Postcondition functions (i.e., the `..._postcondition` functions in the example above) should take their arguments by `const&`, and when they are member functions they should be either `static` or `const` functions. * Similarly, exception guarantee functions (not shown in the example above) should take their arguments by `const&`, and when they are member functions they should be either `static` or `const` functions. -* Old value functions (i.e., the `..._old` functions in the example above) should take their arguments by `const&` a part from old value pointers that should be taken by `&` (so only old value pointers can be modified), and when they are member functions they should be either `static` or `const` functions. +* Old value functions (i.e., the `..._old` functions in the example above) should take their arguments by `const&` apart from old value pointers that should be taken by `&` (so only old value pointers can be modified), and when they are member functions they should be either `static` or `const` functions. * For constructors: Precondition, old value, and exception guarantee functions should be `static` (because there is no valid object `this` if the constructor body does not run successfully, see __Constructor_Calls__). * For destructors: Postcondition functions should be `static` (because there is no valid object `this` after the destructor body runs successfully, but exception guarantee functions do not have to be `static` since the object `this` is still valid because the destructor body did not run successfully, see __Destructor_Calls__). @@ -590,13 +590,13 @@ As shown in __Public_Function_Overrides__ and __Named_Overrides__, this library *Rationale:* The [macroref BOOST_CONTRACT_MAX_ARGS] macro is named after `BOOST_FUNCTION_MAX_ARGS`. ] -These macro cannot be programmed manually but they are not variadic macros (so programmers should be able to use them on any C++ compiler with a sound support for SFINAE). +These macros cannot be programmed manually but they are not variadic macros (so programmers should be able to use them on any C++ compiler with a sound support for SFINAE). [footnote *Rationale:* These macros expand to SFINAE-based introspection template code that are too complex to be programmed manually by users (that remains the case even if C++14 generic lambdas were to be used here). On a related note, in theory using C++14 generic lambdas, the [macroref BOOST_CONTRACT_OVERRIDE] macro could be re-implemented in a way that can be expanded at function scope, instead of class scope (but there is not really a need to do that). ] -The [macroref BOOST_CONTRACT_OVERRIDES] macro is a variadic macro instead but programmes can manually repeat the non-variadic macro [macroref BOOST_CONTRACT_OVERRIDE] for each overriding public function name on compilers that do not support variadic macros. +The [macroref BOOST_CONTRACT_OVERRIDES] macro is a variadic macro instead but programmers can manually repeat the non-variadic macro [macroref BOOST_CONTRACT_OVERRIDE] for each overriding public function name on compilers that do not support variadic macros. [heading Assertions (Not Variadic)] diff --git a/doc/getting_started.qbk b/doc/getting_started.qbk index bdb4b3b1..1498bbfc 100644 --- a/doc/getting_started.qbk +++ b/doc/getting_started.qbk @@ -6,7 +6,7 @@ [section Getting Started] -This section shows how to setup and start using this library. +This section shows how to set up and start using this library. [section This Documentation] @@ -50,7 +50,7 @@ The development and maintenance of this library is hosted on [@https://github.co [section Code Organization] Let [^['boost-root]] be the directory where Boost source files were installed. -This library flies are organized as follows: +This library files are organized as follows: [pre ['boost-root]\/libs\/contract # Directory where this library files are. @@ -115,7 +115,7 @@ $ cd ['boost-root]\/libs/contract/example $ ..\/..\/..\/bjam features-introduction ] -To compile and run all this library's tests (this might take while): +To compile and run all this library's tests (this might take a while): [pre $ cd ['boost-root]\/libs/contract/test @@ -148,7 +148,7 @@ To compile and run the [@../../example/features/introduction.cpp [^['boost-root] >..\\..\\..\\bjam features-introduction ] -To compile and run all this library's tests (this might take while): +To compile and run all this library's tests (this might take a while): [pre >cd ['boost-root]\libs\contract\test diff --git a/doc/introduction.qbk b/doc/introduction.qbk index 85bafeb3..6a806c6a 100644 --- a/doc/introduction.qbk +++ b/doc/introduction.qbk @@ -37,7 +37,7 @@ precondition assertion "x < std::numeric_limits::max()" failed: file "intro Instead, if there is a bug in the implementation of `inc` so that `x` is not incremented by `1` after the execution of the function body then the program will terminate with an error message similar to the following (and it will be evident that the bug is in `inc` body): [footnote -In this example the function body is composed of a single trivial instruction `++x` so it easy to check by visual inspection that it does not contain any bug and it will always increment `x` by `1` thus the function postcondition will never fail. +In this example the function body is composed of a single trivial instruction `++x` so it is easy to check by visual inspection that it does not contain any bug and it will always increment `x` by `1` thus the function postcondition will never fail. In real production code, function bodies are rarely this simple and can hide bugs which make checking postconditions useful. ] @@ -45,7 +45,7 @@ In real production code, function bodies are rarely this simple and can hide bug postcondition assertion "x == *old_x + 1" failed: file "introduction.cpp", line 20 ] -By default, when an assertion fails this library prints an error message such the ones above to the standard error `std::cerr` and terminates the program calling `std::terminate` (this behaviour can be customized to take any user-specified action including throwing exceptions, see __Throw_on_Failures__). +By default, when an assertion fails this library prints an error message such as the ones above to the standard error `std::cerr` and terminates the program calling `std::terminate` (this behaviour can be customized to take any user-specified action including throwing exceptions, see __Throw_on_Failures__). Note that the error messages printed by this library contain all the information necessary to easily and uniquely identify the point in the code at which contract assertions fail. [footnote *Rationale:* @@ -57,7 +57,7 @@ C++11 lambda functions are necessary to use this library without manually writin That said, this library implementation does not use C++11 features and should work on most modern C++ compilers (see __Getting_Started__). ] -In addition to contracts for non-member functions as shown the in the example above, this library allows to program contracts for constructors, destructors, and member functions. +In addition to contracts for non-member functions as shown in the example above, this library allows to program contracts for constructors, destructors, and member functions. These can check class invariants and can also /subcontract/ inheriting and extending contracts from base classes (see [@../../example/features/introduction_public.cpp =introduction_public.cpp=] and __Public_Function_Overrides__): [footnote The `pushable` base class is used in this example just to show subcontracting, it is somewhat arbitrary and it will likely not appear in real production code. diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index 0f56795f..fe6ce989 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -68,7 +68,7 @@ Preconditions must appear before postconditions and exception guarantees when th C++11 lambda functions are convenient to program preconditions, but any other nullary functor can be used (see __No_Lambda_Functions__). [footnote Lambda functions with no parameters can be programmed in C++11 as `[...] () { ... }` but also equivalently as `[...] { ... }`. -This second from is often used in this documentation omitting the empty parameter list `()` for brevity. +This second form is often used in this documentation omitting the empty parameter list `()` for brevity. ] For example, for [funcref boost::contract::function] (similarly for public functions, instead destructors do not have preconditions and constructors use [classref boost::contract::constructor_precondition], see __Public_Functions__, __Destructors__, and __Constructors__): @@ -193,7 +193,7 @@ Non-void virtual public functions and non-void public function overrides must al [section Old Values] -When old values are used in postconditions or in exception guarantees, programmes are responsible to declare local variables before the contract and to assign them to related old value expressions using [macroref BOOST_CONTRACT_OLDOF]. +When old values are used in postconditions or in exception guarantees, programmers are responsible to declare local variables before the contract and to assign them to related old value expressions using [macroref BOOST_CONTRACT_OLDOF]. [footnote The name of a local variable that holds an old value is arbitrary, but [^old_['variable-name]] is often used in this documentation. ] @@ -400,7 +400,7 @@ For example (see [@../../example/features/public.cpp =public.cpp=]): It is not possible to specify preconditions using `.precondition(...)` for constructors (this library will generate a compile-time error if `.precondition(...)` is used on the object returned by [funcref boost::contract::constructor]). Constructor preconditions are specified using the [classref boost::contract::constructor_precondition] base class instead (same considerations as the ones made in __Preconditions__ apply also to the precondition functor passed to [classref boost::contract::constructor_precondition]). -Programmes should not access the object `*this` from constructor preconditions (because the object does not exists yet before the constructor body is executed). +Programmers should not access the object `*this` from constructor preconditions (because the object does not exist yet before the constructor body is executed). [footnote See __No_Lambda_Functions__ to enforce this constraint at compile-time (but not recommended because of extra boiler-plate code). ] @@ -531,7 +531,7 @@ At destruction instead (enclosing destructor exit): # Check static class invariants, by calling [^['type-of]]`(*this)::static_invariant()`. # If the destructor body did not throw an exception: - # Check postconditions, by calling the nullay functor [^['s]]`()` passed to `.postcondition(`[^['s]]`)`. + # Check postconditions, by calling the nullary functor [^['s]]`()` passed to `.postcondition(`[^['s]]`)`. # Else (even if destructors should generally be programmed not to throw in C++): # Check non-static class invariants, by calling `this->invariant()` (because the object was not successfully destructed). # Check exception guarantees, by calling the nullary functor [^['e]]`()` passed to `.except(`[^['e]]`)`. @@ -629,7 +629,7 @@ Virtual public functions must declare an extra trailing parameter of type [class [footnote The name of this extra parameter is arbitrary, but `v` is often used in this documentation. ] -This extra parameter is the last parameter and it has a default value so it does not alter the calling interface of the virtual function (callers will rarely, if ever, have to explicitly deal with this extra parameter a part from when manipulating the virtual function type directly for function pointer type-casting, etc.). +This extra parameter is the last parameter and it has a default value so it does not alter the calling interface of the virtual function (callers will rarely, if ever, have to explicitly deal with this extra parameter apart from when manipulating the virtual function type directly for function pointer type-casting, etc.). Programmers must pass the extra virtual parameter as the very first argument to all [macroref BOOST_CONTRACT_OLDOF] and [funcref boost::contract::public_function] calls in the virtual public function definition. [footnote *Rationale:* diff --git a/include/boost/contract.hpp b/include/boost/contract.hpp index 535e5edc..f83a014f 100644 --- a/include/boost/contract.hpp +++ b/include/boost/contract.hpp @@ -22,7 +22,7 @@ headers are usually not directly included by programmers). All files under the boost/contract/detail/ directory, names within the @c boost::contract::detail namespace, names prefixed by -@c boost_contract_detail... and @c BOOST_CONTRACT_DETAIL... (in any namesapce, +@c boost_contract_detail... and @c BOOST_CONTRACT_DETAIL... (in any namespace, including user's code) are reserved for internal use of this library and should never be used directly by programmers. diff --git a/include/boost/contract/base_types.hpp b/include/boost/contract/base_types.hpp index c6e0a0a9..ba45b049 100644 --- a/include/boost/contract/base_types.hpp +++ b/include/boost/contract/base_types.hpp @@ -8,7 +8,7 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -Specify inheritance form base classes (for subcontracting). +Specify inheritance from base classes (for subcontracting). */ // IMPORTANT: Included by contract_macro.hpp so must #if-guard all its includes. diff --git a/include/boost/contract/call_if.hpp b/include/boost/contract/call_if.hpp index 9a658aaa..74dd8faa 100644 --- a/include/boost/contract/call_if.hpp +++ b/include/boost/contract/call_if.hpp @@ -260,7 +260,7 @@ Usually this class template is instantiated only via the return value of @see @RefSect{extras.assertion_requirements__templates_, Assertion Requirements} -@tparam Then Type of functor template to call when the static predicate if +@tparam Then Type of functor template to call when the static predicate is @c true (as it is for this template specialization). */ template @@ -452,7 +452,7 @@ struct call_if_statement diff --git a/include/boost/contract/core/virtual.hpp b/include/boost/contract/core/virtual.hpp index b9aa09f5..aad00048 100644 --- a/include/boost/contract/core/virtual.hpp +++ b/include/boost/contract/core/virtual.hpp @@ -63,7 +63,7 @@ This extra parameter must be passed to @RefFunc{boost::contract::public_function}, @RefMacro{BOOST_CONTRACT_OLDOF}, and all other operations of this library that accept a pointer to @RefClass{boost::contract::virtual_}. -A part from that, this class is not intended to be directly used by programmers +Apart from that, this class is not intended to be directly used by programmers (and that is why this class does not have any public member and it is not copyable). diff --git a/include/boost/contract/destructor.hpp b/include/boost/contract/destructor.hpp index a153723a..484fb892 100644 --- a/include/boost/contract/destructor.hpp +++ b/include/boost/contract/destructor.hpp @@ -76,7 +76,7 @@ postconditions and exception guarantees, within classes that have no invariants. volatile invariants, see @RefSect{tutorial.class_invariants, Class Invariants} and @RefSect{extras.volatile_public_functions, - Volatile Public Functions}). + Volatile Public Functions}.) @tparam Class The type of the class containing the destructor declaring the contract. diff --git a/include/boost/contract/old.hpp b/include/boost/contract/old.hpp index 6fe5edc7..e866c7cb 100644 --- a/include/boost/contract/old.hpp +++ b/include/boost/contract/old.hpp @@ -129,7 +129,7 @@ namespace boost { namespace contract { Trait to check if an old value type can be copied or not. By default, this unary boolean meta-function is equivalent to -@c boost::is_copy_constructible but programmers can chose to specialize it +@c boost::is_copy_constructible but programmers can choose to specialize it for user-defined types (in general some kind of specialization is also needed on compilers that do not support C++11, see @@ -232,7 +232,7 @@ class old_ptr_if_copyable; /** Old value pointer that requires the pointed old value type to be copyable. -This pointer can be set to point an actual old value copy using either +This pointer can be set to point to an actual old value copy using either @RefMacro{BOOST_CONTRACT_OLDOF} or @RefFunc{boost::contract::make_old} (that is why this class does not have public non-default constructors): @@ -351,7 +351,7 @@ This pointer can be set to point to an actual old value copy using either @RefMacro{BOOST_CONTRACT_OLDOF} or @RefFunc{boost::contract::make_old}: @code -template // Type `T` might or not be copyable. +template // Type `T` might or might not be copyable. class u { public: virtual void f(..., boost::contract::virtual_* v = 0) { @@ -561,7 +561,7 @@ class old_pointer { // Copyable (as *). public: /** Convert this object to an actual old value pointer for which the old value - type @c T might or not be copyable. + type @c T might or might not be copyable. For example, this is implicitly called when assigning or initializing old value pointers of type @c boost::contract::old_ptr_if_copyable. diff --git a/include/boost/contract/public_function.hpp b/include/boost/contract/public_function.hpp index 520e1155..e6d9bddf 100644 --- a/include/boost/contract/public_function.hpp +++ b/include/boost/contract/public_function.hpp @@ -143,7 +143,7 @@ specify_precondition_old_postcondition_except<> public_function() { /** Program contracts for public functions that are not static, not virtual, and do -not not override. +not override. This is used to specify preconditions, postconditions, exception guarantees, old value copies at body, and check class invariants for public functions that are diff --git a/include/boost/contract_macro.hpp b/include/boost/contract_macro.hpp index 2b1295a0..1c6d2b85 100644 --- a/include/boost/contract_macro.hpp +++ b/include/boost/contract_macro.hpp @@ -56,7 +56,7 @@ Disable Contract Compilation}). Where: - @arg f is the nullay functor called by this library to + @arg f is the nullary functor called by this library to check preconditions @c f(). Assertions within this functor are usually programmed using @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a call @@ -180,7 +180,7 @@ Disable Contract Compilation}). Where: @arg f is the nullary functor called by this library - @c f() to assign old value copies just before the body is execute + @c f() to assign old value copies just before the body is executed but after entry invariants (when they apply) and preconditions are checked. Old value pointers within this functor call are usually assigned @@ -327,7 +327,7 @@ Disable Contract Compilation}). be copyable: @code - template // Type `T` might or not be copyable. + template // Type `T` might or might not be copyable. class u { public: void f(...) { @@ -506,8 +506,8 @@ Disable Contract Compilation}). invariants for public functions that are not static and not volatile (see @RefMacro{BOOST_CONTRACT_STATIC_INVARIANT} and @RefMacro{BOOST_CONTRACT_INVARIANT_VOLATILE}). - The curly parenthesis are mandatory (rationale: this is so the - syntax of this macro resembles mote the syntax of the lambda + The curly parentheses are mandatory (rationale: this is so the + syntax of this macro resembles more the syntax of the lambda functions usually used to specify preconditions, etc.). Assertions within this function are usually programmed using @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a call @@ -546,7 +546,7 @@ Disable Contract Compilation}). invariants for volatile public functions (see @RefMacro{BOOST_CONTRACT_INVARIANT} and @RefMacro{BOOST_CONTRACT_STATIC_INVARIANT}). - The curly parenthesis are mandatory. + The curly parentheses are mandatory. Assertions within this function are usually programmed using @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a call to this function indicates a contract assertion failure (and will @@ -585,7 +585,7 @@ Disable Contract Compilation}). invariants for static public functions (see @RefMacro{BOOST_CONTRACT_INVARIANT} and @RefMacro{BOOST_CONTRACT_INVARIANT_VOLATILE}). - The curly parenthesis are mandatory. + The curly parentheses are mandatory. Assertions within this function are usually programmed using @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a call to this function indicates a contract assertion failure (and will