Member vs. Free-standing Functions
Like in Matplotlib, we support two coding styles: Free-standing functions and an Object-oriented interface.
These two examples would generate the same plot:
1 2 3 | |
1 2 3 | |
-
Freestanding functions:
- We call functions to create plots on the current axes
- The global current
axesobject is the currentaxesobject in the current figure in the global figure registry - For instance, one can use
plot(y);to create a line plot on the current axes (or create a newaxesobject if needed). - Also, one can use
plot(ax,y);to create a line plot on theaxesobjectax. - This is less verbose for small projects and quick tests.
- The library looks for existing axes to create the plot.
-
Object-oriented interface:
- We explicitly create figures and call methods on them
- For instance, one can use
ax->plot(y);to plot on theaxesobjectax - We can create the same line plot on the current axes by
auto ax = gca(); ax->plot(y); - This is less verbose and provides better control in large projects where we need to pass these objects around
- The user manages axes handles containing plots.
All free-standing functions are templated functions that use meta-programming to call the main function on the current axes object. If the first parameter is not an axes_handle, it will get an axes_handle from the figure registry with gca (Section Axes Object) and forward all parameters to the function in this axes object. If the first parameter is an axes_handle, the template function will forward all parameters, but the first one, to this axes object. This use of templates for the free-standing functions keeps both coding styles maintainable by the developers.
Note that, because the example needs the axes object for the function my_function, we also need to get a reference to the axes object with the free-standing functions. In that case, the free-standing functions are not less verbose than the object-oriented interface.
To adhere to free-standing functions, we could create two versions of my_function: one that receives an axes_handle, and a second version that would get an axes_handle from the figure registry and call the first version. If my_function is going to be exposed to other users as a library, this could be a convenience to these users. However, notice that this is only moving the verbosity from the main function to my_function. In fact, this is how the free-standing functions in Matplot++ work.