# C++ Style Guide Please follow these guidelines when submitting patches. ## Whitespace Use 4 spaces. Format ``if`` as follows: if (d.find(t) == d.end()) { d[t] = coef; } else { d[t] = d[t] + coef; } ## Pointers Never use raw C++ pointers and never use the raw `new` and `delete`. Always use the smart pointers provided by `symengine_rcp.h` (depending on `WITH_SYMENGINE_RCP`, those are either Teuchos::RCP, or our own, faster implementation), i.e. `Ptr` and `RCP` (and do not use the `.get()` method, only the `.ptr()` method). In Debug mode, the pointers are 100% safe, i.e. no matter how you use them the code will not segfault, but instead raise a nice exception if a pointer becomes dangling or null. In Release mode, the `Ptr` is as fast as a raw pointer and `RCP` is a lot faster, but no checks are done (so the code can segfault). ### Declaration In the `.cpp` files you can declare: using SymEngine::RCP; using SymEngine::Ptr; using SymEngine::outArg; using SymEngine::make_rcp; using SymEngine::rcp_dynamic_cast; and then just use `RCP` or `Ptr`. In the `.h` header files use the full name like `SymEngine::RCP` or `SymEngine::Ptr`. ### Initialization Initialize as follows: RCP x = make_rcp("x"); Never call the naked `new`, nor use the naked `rcp`. If available, use the factory functions, e.g. in this case `symbol()` as follows: RCP x = symbol("x"); This does the same thing (internally it calls `make_rcp`), but it is easier to use. ### Freeing The `RCP` pointer is released automatically. You never call the naked `delete`. ### Passing To/From Functions Use C++ references for objects that you are **not** passing around. If the object is *not* modified, use `const A &a`: RCP gcd(const Integer &a, const Integer &b) { integer_class g; mp_gcd(g, a.as_integer_class(), b.as_integer_class()); return integer(std::move(g)); } If it *is* modified, use `A &a` (see the first argument): void Add::dict_add_term(umap_basic_num &d, const RCP &coef, const RCP &t) { if (d.find(t) == d.end()) { d[t] = coef; } else { d[t] = d[t] + coef; } } If the objects **are** passed around, you have to use `RCP`. You also need to use `RCP` whenever you call some function that uses `RCP`. Declare functions with two input arguments (and one return value) as follows: RCP multiply(const RCP &a, const RCP &b) { ... return make_rcp(1); } Functions with one input and two output arguments are declared: void as_coef_term(const RCP &self, const Ptr> &coef, const Ptr> &term) { ... *coef = make_rcp(1); *term = self ... } and these are used as follows: RCP coef; RCP t; as_coef_term(b, outArg(coef), outArg(t)); `SymEngine` objects are always immutable, so you always declare them as `const`. And `RCP` is only used with `SymEngine`'s objects, so you always use `const RCP &i`. But if the `Integer` was somehow mutable (it's not in `SymEngine`), you would use `const RCP &i`. For returning objects from functions, simply declare the return type as `RCP` as shown above. ### Casting You can use dynamic cast as follows: RCP tmp; RCP coef; coef = rcp_dynamic_cast(tmp); ## Namespaces Never use "implicit imports": ``using namespace std;``. In cpp files, either use the full name of the symbol (e.g. ``SymEngine::RCP``), or use "explicit import" as follows: ``using SymEngine::RCP;``. In header files, always use the full name (never import symbols there).