|
| 1 | +--- |
| 2 | +layout: default |
| 3 | +title: Member vs. Free-standing Functions |
| 4 | +nav_order: 1 |
| 5 | +has_children: false |
| 6 | +parent: Coding styles |
| 7 | +has_toc: false |
| 8 | +--- |
| 9 | +# Member vs. Free-standing Functions |
| 10 | + |
| 11 | +Like in Matplotlib, we support two coding styles: Free-standing functions and an Object-oriented interface. |
| 12 | + |
| 13 | +* Freestanding functions: |
| 14 | + - We call functions to create plots on the current axes |
| 15 | + - The global current `axes` object is the current `axes` object in the current figure in the global figure registry |
| 16 | + - For instance, one can use `plot(y);` to create a line plot on the current axes (or create a new `axes` object if needed). |
| 17 | + - Also, one can use `plot(ax,y);` to create a line plot on the `axes` object `ax`. |
| 18 | + - This is less verbose for small projects and quick tests. |
| 19 | + - The library looks for existing axes to create the plot. |
| 20 | + |
| 21 | +* Object-oriented interface: |
| 22 | + - We explicitly create figures and call methods on them |
| 23 | + - For instance, one can use `ax->plot(y);` to plot on the `axes` object `ax` |
| 24 | + - We can create the same line plot on the current axes by `auto ax = gca(); ax->plot(y);` |
| 25 | + - This is less verbose and provides better control in large projects where we need to pass these objects around |
| 26 | + - The user manages axes handles containing plots. |
| 27 | + |
| 28 | +Assuming the user is explicitly managing the axes to create plots in another function, a more complete example of these styles could be |
| 29 | + |
| 30 | +```cpp |
| 31 | +// Free-standing functions |
| 32 | +auto ax = gca(); |
| 33 | +plot(ax, x, y)->color("red").line_width(2); |
| 34 | +my_function(ax); |
| 35 | +``` |
| 36 | +
|
| 37 | +and |
| 38 | +
|
| 39 | +```cpp |
| 40 | +// Object-oriented interface |
| 41 | +auto ax = gca(); |
| 42 | +ax->plot(x, y)->color("red").line_width(2); |
| 43 | +my_function(ax); |
| 44 | +``` |
| 45 | + |
| 46 | +Both examples would generate the same plot. 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](../examples/appearance/axes-object.md)) 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. |
| 47 | + |
| 48 | +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. |
| 49 | + |
| 50 | +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. |
| 51 | + |
| 52 | + |
| 53 | + |
0 commit comments