====== 2014-07-12 - faster by encapsulation ======
encapsulation usually means for ppl abstraction and abstraction in turn is often blamed for decreasing performance. this is not [[wp>C++]] style. C++ is all about lightweight abstractions. the same way one can have abstract algorithms like //sort//, that are highly optimized and fast, the same way encapsulation can be used for speeding things up.
===== input example =====
as an example consider raw pointer to some type //X// and two functions operating on it:
int foo(X* ptr)
{
if(not ptr)
throw std::runtime_error{"unexpected null"};
return ptr->getNumber() + 42;
}
double bar(X* ptr)
{
if(not ptr)
throw std::runtime_error{"unexpected null"};
return ptr->averageValue() / 4.2;
}
what do they have in common? they both do simple things, obfuscated by constant not-null checking.
===== encapsulation =====
now imagine class, that would ensure pointer held inside is not null. something as simple as this:
template
struct NotNull
{
explicit NotNull(T* t):
t_{t}
{
if(not t_)
throw std::runtime_error{"pointer is null"};
}
// more operators, c-tors, etc...
T* operator->() { return t_; }
// more getters, swaps, etc...
private:
T* t_;
};
now lets use it in our previous code:
int foo(NotNull ptr)
{
return ptr->getNumber() + 42;
}
double bar(NotNull ptr)
{
return ptr->averageValue() / 4.2;
}
code just got shorter and more readable. it also auto-protects from mistakes -- null-pointers dereferences are no longer a problem.
but how it got faster? notice that now you need to do not-null check only once -- in a constructor. from that point, merely knowing type ensures you the pointer cannot be null, so you no longer need to check it! it means not only less code, but a faster code -- not chance of branch miss-prediction. :) this may not appear to be lot, but when you multiply this by number of method/functions in your project, gain will became obvious. plus you get shorter code, for free. :D
presented idea is a [[wp>RAII]] way of expressing properties, as an extension of usual "ownerships". logically it works exactly the same way RAII constructors do: once constructor is done, each method needs not to check if object is initialized. this way property can be encapsulated in a type, to free user from checking certain invariants at each step.
===== genesis =====
the idea is not new to me. it first crossed my mind when we were developing [[wp>ACARM-ng]]. as we had a chance to make the whole system from scratch, many interesting ideas popped out at that time. on of this was to make boost::shared_ptr version, that cannot be null. since system is open source, you can [[https://github.com/el-bart/ACARM-ng/blob/master/src/commons/Commons/SharedPtrNotNULL.hpp|check out the original implementation]].
it all worked like a charm! simple, valid code without extra checks, where not needed. exactly what one needs! :)
this was back in [[wp>C++03]] era. now we can do more. i plan to implement general pointer wrapper (NotNull<>) as a part of [[https://github.com/el-bart/but|Basic Utilities and Tools]] library.