
The documentation lists the following sequence for executing a constructor:
1. Initialize member variables via the constructor member initialization list (if such a list is specified). 2. Check preconditions (but not invariants). 3. Execute constructor body. 4. Check invariants. 5. Check postconditions.
I believe, one of the reasons for validating arguments of a constuctor is to not allow the incorrect values to initialize objest's sub-objects (members). I believe the sequence of the first two items should be inverse. Am I wrong?
The library follows Eiffel semantics for constructor which is {Default AND Pre}Body{Post AND Inv} where Default is default initialization of members (similar to C++ member initialization list). That said, it would be difficult to implement a different semantics (like the one you suggest) in C++ because of the lack of delegating constructors.
The sole fact that other language implements it this way is not sufficient an argument. I can think of the situation when "Eiffel order" may cause damage that the inverse order might have prevented: Type::Type( int & counter ) precondition{ counter < MAX; } : handle( irreversibleChange(int--) ) { ; } Suppose the constructor of Type is called, and the value of counter is MAX. This value is invalid, but by the time the precondition is checked, the irreversibleChange is executed, and the value of counter is reduced, so the assertion concludes that everything is fine. Now, the argument that it is difficult to implement is convincing; it may be that it is impossible at all. But I would call not having the {Pre->Init} order a limitation of the library. Let me be clear: one tiny limitation in the great library, because out of many attempts to provide contract programming to C++ I have seen, this is the only one that really looks good. Regards, &rzej