On 21.07.2016 23:25, Mr Flibble wrote:
> The Liskov substitution principle always works if you follow it. You
> are DOING IT WRONG (TM).
Liskov principle says that a derived class must always be fully
functional when accessed via base class interface. That's no problem
with my classes. Instead, my problem is that because of callback
mechanism the base class object might be accessed via derived class
interface, and Liskov principle does not say anything about this.
To clarify: my Base and Derived correspond roughly to
std::vector::const_iterator and std::vector::iterator. Derived is
derived from Base so that casting a pointer/reference of Derived to a
pointer/reference of Base would always work seamlessly/automatically,
*including* with arrays of Derived (I am guaranteeing
sizeof(Derived)==sizeof(Base)). That's Liskov in work, BTW - a mutable
object can always be accessed via a non-mutable interface as well.
However, regarding arrays of derived class objects - this is where C++
fails hard if the sizes are not the same (and I suspect it might be
formally UB even if sizes are the same(?)). So it appears C++ itself has
some troubles with supporting Liskov (in arrays of objects).
Here is some example code about what I mean by a Liskov substitution of
an array:
#include <vector>
void foo(std::vector<int>::const_iterator* array, int len) {
int x = *(array[len-1]);
}
int main() {
std::vector<int> test = {1, 2, 3};
std::vector<int>::iterator arr[3] =
{test.begin(), test.begin()+1, test.begin()+2};
foo(arr, 3);
}
Curiously, MSVC derives std::vector::iterator from
std::vector::const_iterator so it compiles and runs this example fine,
but g++ does not (effectively failing Liskov):
main.cpp: In function `int main()':
main.cpp:33:12: error: cannot convert `std::vector<int>::iterator* {aka
__gnu_cxx::__normal_iterator<int*, std::vector<int> >*}' to
`std::vector<int>::const_iterator* {aka
__gnu_cxx::__normal_iterator<const int*, std::vector<int> >*}' for
argument `1' to `void foo(std::vector<int>::const_iterator*, int)'
foo(arr, 4);