- summary changed from Fix infinite recursion if BODY not used for base function calls to fix infinite recursion if BODY not used for base function calls
- milestone changed from Release to Future
If an overriding function does not use BODY() to call the overridden function, contracts go into infinite recursion.
This is an important limitation and I should try to remove it.
I think it is not possible to work around this limitation.
Using object state the library could detect infinite recursion between overriding and overridden function (I prototyped something like this but I am not even sure if this is 100% possible).
However, to break the recursion the base contract will have to call the base body function via static binding (otherwise using dynamic binding, default C++ behaviour for the call, the overriding function will be called causing the recursion).
The contract itself cannot perform the static binding call (e.g., using static_cast<> to the object) because the object state is changed only if pointers/references to the objects are used to call the body, but if pointers/objects are used then C++ uses dynamic binding for the call.
So the contract function could call a special method of the contracted class which performs the static binding call contract_static_binding_body_....
The issue is that such a static binding call will raise a compiler error if the body function is pure virtual -- but can I use SFINAE to get around this compiler error??
The library does not know directly when a function is pure virtual or not so the library will have to define contract_static_binding_body_... also for pure virtual functions and in this case the static binding call B::f() will raise a compile time error.
BUT, could I use templates so the contract_static_biding_body_ is templated and it is not compiled unless called? This way I only get the error if the use calls attempts the static binding for pure virtual??
struct base {
virtual void call() {
std::cout << "base call\n";
// body(); // This causes infinite recursion as it calls deriv::body() via dynamic binding.
static_binding_body();
}
void static_binding_body() {
std::cout << "base static binding body\n";
b::body(); // Compiler error for pure virtual body()...
}
virtual void body() = 0;
// {
// std::cout << "base body\n";
// }
};
struct deriv: base {
virtual void call() {
std::cout << "deriv call\n";
body();
}
virtual void body() {
std::cout << "deri body\n";
base::call(); // Causes infinite recursion...
// base::body(); // This is fine instead.
}
};
Infinite recursion: deriv::base --> deriv::body --> base::call() --> deriv::body() causing infinite recursion because base::body() is NOT called...
So, at the moment, I did not see a way around this. Programmers have to pay attention and use BODY() for static binding call of the base class.
Log in to post a comment.