
From a mathematical point of view the complex z is a complex number of course, and z/|z| (z/abs(z)) is not only also a complex number but also potentially a complex_unit_circle element with very spefic
Hi, I find proto pretty intriguing and I can see the power in it but I am still not able to create a context in which it can help in my design. I also find the Boost.Proto examples very confusing and not usually in the context I always imagine to use the library. There are several concepts that I don't yet fully understand like "context" and "grammars". Also besides the power I see in the library sometimes the resulting syntax in the examples is pretty disappointing, with all those "eval" functions. In general I can't see whether this is a result of limitations of the library or a tool to make the examples more pedagogical. If someone is kind enough to follow me and help me during this discovery of the library along these posts I will continue. The idea of this post is try to bring a simple example of boost at a context that I am able to understand. In order to be useful for many other people I will try to bring proto to a purely mathematical level. Suppose I want to build a new (kind of mathematical) library. Typically I would start defining a lots of arithmetical objects and members and friends operators, all of them eager (member)functions, lots of operators (many bugs also), also use boost.operators (to make less bugs) and then realise that the library has not any real deep mathematical structure on it, not to the compile-time/programmer level. Yes, the program will be able to do a lot of mathematics at runtime via numerical representations but there will be no insight from the point of view of the program code or the "type system". Let's start by an example, I define a complex type, after a lot of work I would have made the equivalent of std::complex<T>. Then the program replaces T by double and the program can (at runtime) do some "math". The problem is that I as a programmer can not do any math with that type. Let me give a concrete example, the complex_unit_circle is a set of complex numbers with modulus =1. One is tempted to implement complex_unit_circle in terms of the "complex type" or some parameterisation (angle). properties. For example the product of two elements of the unit circle can be interpreted as a unit circle element again. The only way to express this potentiality at compile time is by expression templates, i.e. in its most glorious state by Boost.Proto. z/abs(z) is really an expression that eventually can be used to construct either another complex number (as type) or a unit circle number (as type). But lets start slower than that, lets build an expression that can be used (potentially) to build a complex number instead. The concrete question of this post will be how to obtain the desired syntax by adding layers to the original posted code. This is what I have done so far: #include <boost/proto/core.hpp> namespace pretty{ namespace proto = boost::proto; struct i_tag{}; proto::terminal< i_tag >::type const i = {{}}; } int main(){ using namespace pretty; 4. + 5.*i; //this will be a complex number (in some sense) return 0; } of course this program does nothing, it is just to show that I can create a expression template with a symbol called "i", this symbol will have properties that will eventually make it equivalent to one of the roots of -1 (mathematically speaking) (but not yet). Note that I didn't define any so called "grammar" or "context" yet. Since the first concern is to be able to use the new code with old code at all intermediate steps in the development, duppose I want to use this kind of expression to construct (in the c++ sense) an existing type, namely std::complex<double>. i.e. I want to be able to write: std::complex<double> z = 4. + 5.*i; or std::complex<double> z(4. + 5.*i); (forget about alternative notations, like 5.*i + 4. or 4. + i*5) The only ways I see this is possible is by adding either a constructor to std::complex<double> or a cast operator of the "expression of type 4.+5.*i" to std::complex<double>. The question for this post, 1) is this true? 2) if yes, then that means that one of the 2 types (type complex or typeof(4.+5.*i) ), will have to be modified (or extendended) in other to accept this syntax. 3) if no , how can I allow this syntax? 4) if the std::complex type is not modifiable, what is the mechanism in proto to define a cast over a certain set of expressions, e.g. of the type of 4.+5.*i. 5) if not, is this syntax not possible at all? is it here where we need to introduce those "eval" functions such as std::complex<double> z = eval_as_complex(4. + 5.*i). The idea is that once I resolve this general questions about the library I will continue building up. (And excuse me for these naive questions along the way). (Note: I know that std::complex<double> had constructor std::complex<double>(4.,5.) and that should be the preferred use, but this post is all about "syntax" and how to use proto, these are just examples). Thank you, Alfredo