AST<float> p1 = exp.GetP1();
AST<float> rsqr = p1 * p1; // AST<float> implements an operator* overload that produces an AST<float> object
Even if many frown upon operator overloading due to the annoying magical-ness of the standard-librarys appropriation of the shift operators for "piping" (<< and >>), it's still what makes many people prefer C++ for vector-math,etc tasks.
So whilst the result isn't a direct multiplication it should still be an acceptable use since the resulting code will actually be doing multiplications.
Considering what goes on under the hood however, I guess there might be some compiler optimization reasons to keep everything in the expression object in the example as the holder of data instead of spread out in an allocation tree with lots of pointer-chasing.