Avoid std::shared_ptr to maximize RVO

Replace UnsafeTerm with SharedExpr, a smart pointer implementation
for symbolic expressions. This more often allows the compiler to
optimize the return value of functions (avoiding copy and/or move
constructors).

In experiments where the SMT/SAT solver calls are bypassed,
this consistently improves performance (sometimes up to 25%).

A current downside is that I could not get the implicit conversion
operator to work yet due to ambiguous overloads of binary operators.
For now, this issue is side stepped by explicitly overloading those
operators for Bool and SharedExpr arguments, something that should be
reinvestigated in the future.