# Writing Generic Code (Advanced Bronze)

Generic code is an important concept in informatics. Of course, as all concepts go, you may dodge generic code and continue to write in a hyper-specific style. As such, begin by questioning purpose.&#x20;

PURPOSE: Why write generic code?

Generic code is **adaptable**, meaning that it can be put to use immediately in many ways without major changes. It can be reused, extended, and even versioned powerfully to save time. Time is of essence in informatics, where I refer to both algorithmic time _complexity_ and _coding_ time.

Even if you are writing a very specific data structure or algorithm, to truly grasp it, a good contemplation is "Can I generalize what I have learned to a broader class of problems?" Answer this by then attempting to generalize.&#x20;

That said, before you proceed, I issue the below warning:

Generic code can easily assist black-boxing, where you write a snippet of code such that you either forget its meaning or have no idea what it means in the first place. This is a common pitfall, and you should avoid this as much as possible if you truly want to grasp a concept in informatics.&#x20;

Modern C++, a groundbreaking language in the current informatics scene, indeed has several builtin features to support and streamline generic code. Here, we will cover the basic important ones you will definitely want to add to your coding arsenal.&#x20;

### Classes & Structs

**Classes** are by far the most important utility in extensible code. If you ever want to write a data structure that has several member functions to process stored data, classes are for you. Of course, classes can have public and private sections. For instance, consider a class `human`, which maintains several relevant member functions.&#x20;

```cpp
#include <bits/stdc++.h>
using namespace std; 

class human {
    private: //intrinsic properties
        int body_temperature, temper
        string name; 
    public: //external reactions
        string id() { //what do other people call him
            return name; 
        }
        string feeling() { //answers "how do I feel"
            if(body_temperature >= 97 && body_temperature <= 99) return "good"; 
            else return "bad"; 
        }
        string emotion() {
            if(temper <= 10) return "sad"; 
            else if(temper <= 30) return "happy"; 
            else return "angry";
        }
};
```

But how do we actually use (and reuse) this class data structure we have created? We do this by creating _instances_ of this class, concretely known as **objects**.&#x20;

Below is an example instance of the `human` class, a `human` object named `Sal`. &#x20;

```cpp
human Sal; 
```

Of course, we will want to initialize any object of this `human` class with its fundamental attributes (`body_temperature` and `temper` from the above), but the problem here is that we are unable to access them directly; they are private and remain uninitialized.&#x20;

To partially alleviate this, we can initialize variables in the class declaration itself:&#x20;

```cpp
class human {
    private: //intrinsic properties
        int body_temperature = 98, temper = 25; 
        string name = "Sal"; 
    public: //external reactions
        string id() { //what do other people call him
            return name; 
        }
        string feeling() { //answers "how do I feel"
            if(body_temperature >= 97 && body_temperature <= 99) return "good"; 
            else return "bad"; 
        }
        string emotion() {
            if(temper <= 10) return "sad"; 
            else if(temper <= 30) return "happy"; 
            else return "angry";
        }
};
```

This gives us something to work with, and we can now create `Sal` in `main()` as well as call his member functions (instantiated directly from the base `human` class).&#x20;

```cpp
int main() {
    human Sal; 
    cout << Sal.id() <<  " feels " << Sal.feeling() << " and is " << Sal.emotion() 
    << "\n"; 
}
```

To completely solve this, we might be forced to make these variables public, but instead we can be more clever and write a **constructor** function for this class, essentially a function that is automatically called whenever an instance of the class is created. Constructors are useful when we want to prevent modification to variables we create but be able to initialize them for use, making them naturally the most viable option for proprietary software companies.&#x20;

We can create a constructor for the human class and require initialization of the variables `body_temperature` and `temper`, which gives us some control over `Sal`'s intrinsic properties as they are initialized. The overall code becomes:

```cpp
#include <bits/stdc++.h>
using namespace std; 

class human {
    private: //intrinsic properties
        int body_temperature, temper; 
        string name; 
    public: //external reactions
        human(string _name, int _body_temperature, int _temper) {
            name = _name; 
            body_temperature = _body_temperature, temper = _temper; 
        }
        string id() { //what do other people call him
            return name; 
        }
        string feeling() { //answers "how do I feel"
            if(body_temperature >= 97 && body_temperature <= 99) return "good"; 
            else return "bad"; 
        }
        string emotion() {
            if(temper <= 10) return "sad"; 
            else if(temper <= 30) return "happy"; 
            else return "angry";
        }
};

int main() {
    human Sal("Sal", 98, 25); 
    cout << Sal.id() << " feels " << Sal.feeling() << " and is " << Sal.emotion() 
    << "\n"; 
}
```

This is immediately very extensible if we wish to create multiple instances of `human`, all with their own initial properties. In fact, we can be even more general by creating an external function condition that easily states feelings and emotions for us without having to be rewritten.&#x20;

```cpp
void condition(human h) {
    cout << h.id() << " feels " << h.feeling() << " and is " << h.emotion(); 
}

int main() {
    human Sal("Sal", 98, 25), Bob("Bob", 100, 9), Joe("Joe", 85, 35); 
    condition(Sal), condition(Bob), condition(Joe); 
}
```

As one very specific but useful note on constructors, when we wish to merely initialize properties, we can adopt an alternative declaration that executes significantly faster than the first; using the argument name as the variable itself also becomes permissible and is guaranteed defined behavior:&#x20;

```cpp
human(string name, int body_temperature, int temper) : 
name(name), body_temperature(body_temperature), temper(temper) {}
```

**Structs** are useful when we care less about keeping private properties and more about having just a general reusable data structure. This means everything is public in a struct by default, and a `human` struct, along with the reformatted constructor above, would look like:

```cpp
struct human {
    int body_temperature, temper; 
    string name; 
    human(string name, int body_temperature, int temper) : 
    name(name), body_temperature(body_temperature), temper(temper) {}
    string id() { //what do other people call him
        return name; 
    }
    string feeling() { //answers "how do I feel"
        if(body_temperature >= 97 && body_temperature <= 99) return "good"; 
        else return "bad"; 
    }
    string emotion() {
        if(temper <= 10) return "sad"; 
        else if(temper <= 30) return "happy"; 
        else return "angry";
    }
};
```

Immediately, our struct is easier to manage given its open nature. It is more integrated with the surrounding code, and we can do manipulations like:

```cpp
human Sal("Sal", 98, 25); 
condition(Sal); //get Sal's initial condition
Sal.name = "Sally" //Sal's friends sometimes call him Sally
Sal.body_temperature = 102; //Sal gets sick
Sal.temper = 40; //he develops bad temper 
condition(Sal); //now, get Sal's new condition
```

Finally, we can choose to discard the constructor altogether and opt for an initializer list based on the _order_ of the declaration of intrinsic variables. In the `human` case, the variables in order are `body_temperature`, `temper`, and `name`, so we can remove the constructor and opt for an initializer list like:&#x20;

```cpp
human Sal{"Sal", 98, 25}; 
```

Needless to say, all of this enables very clean initialization and manipulation of classes and structs, integral to generic code.&#x20;

### Templates

The `human` class example, though well-defined, was mostly intended to serve as an example of the versatility of classes and structs. We now switch to something simpler. Imagine a three-dimensional point in space as the following struct, where we create some sample instances `P1` and `P2`

```cpp
struct pt {
    int x, y, z; 
} P1{1, 2, 3}, P2{3, 4, 5}; // we can make quick instances right before the ;
```

But what if we wanted to make a `P3` point with coordinates as doubles? We would then be forced to create a secondary point struct `pt1`:

```cpp
struct pt { int x, y, z; } P1{1, 2, 3}, P2{3, 4, 5}; 
struct pt1 { double x, y, z; } P3{1.1, 2.2, 3.3};  
```

This might not seem too bad immediately, but imagine having to create structs like this over and over again just to accommodate various type changes. We need something better.&#x20;

Lo and behold, the **template** to the rescue. We can use the format `template<...>` to specify the specific templating conditions and then simply define the struct normally. In particular, if we use a class `T`, we achieve:

```cpp
template<class T> struct pt { T x, y, z; }; 
pt<int> P1{1, 2, 3}, P2{3, 4, 5}; 
pt<double> P3{1.1, 2.2, 3.3}; 
pt<long long> P4{9223372036854775807, 9223372036854775807, 9223372036854775807}; 
```

It would be narrow-minded to think that templates are in any way limited to classes and structs. They can be used with functions and much more. One interesting use case is that of the size of various containers. The size member function of a container usually returns a type incompatible with integer, but we can easily write a templated function to fix this, handling all class types `T` of container at once:

```cpp
template<class T> inline int sz(T container) {
    return (int)container.size(); 
}
```

You may apply this as `sz<vector<int>>(v)` on some `vector<int> v`, but since C++11, functions (but not classes or structs until C++14 and C++17) can actually infer template arguments, meaning that we can simply use `sz(v)`!

What if we wanted to put multiple arguments in a template to handle multiple classes? Consider the below secondary pair comparator struct as an example:

```cpp
struct CPS {
    template<class T, class U>
    bool operator() (const pair<T, U>& a, const pair<T, U>& b) {
        return make_pair(a.second, a.first) < make_pair(b.second, b.first); 
    }
}; 
```

And in this design, since the template arguments both apply to only a function, they can be easily inferred! For instance, declaring a set of `pair<double, int>` in C++11 is as easy as `set<pair<double, int>, CPS>`.&#x20;

What constitutes what other kinds of types we can put in templates? As a general rule of thumb, until C++17, the types valid in template arguments are only classes and fundamental types, of which only classes can be directly inferred in many cases by functions.&#x20;

In fact, we can even have templates that take a variable number of arguments, known as variadic templates, or templates within templates, known as nested templates, both of which are beyond the scope of this basic exposition but can be found [here](https://en.cppreference.com/w/cpp/language/parameter_pack) and [here](https://blog.feabhas.com/2014/08/templates-of-templates/).

As a fun fact, just as templates give us so much control over the generality of the language, a lot of the C++ standard in itself is written generically with templates under the hood.&#x20;

### Macros

Macros are infamous among many C++ users as terrible due to almost inevitable confusion when developers collaborate with each other. Nevertheless, macros are important to many in the informatics community to simplify notations in the standard.&#x20;

Among various types of macros you will see are keywords such as `typedef`, `using`, and `#define`. Of these, `typedef` is now rather outdated (though still used by some) because it is more or less just an annoying version of `using` with frustrating semantics, so we will not cover it here.&#x20;

We start with `using`. This is a fascinating keyword, frequently used to simplify namespace prefixing when applicable. For instance, statements like

```cpp
using namespace std; 
```

actually allow us to use an entire namespace. Of course, since `using namespace std` is frequently limited to the competitive programming community and looked down upon otherwise, we can use `using` to invoke better simplifications.&#x20;

Suppose that a lot of my code uses`std::cout`, which I find frustrating to type. I can write

```cpp
using std::cout; 
```

and then just live with `cout`. But what if I was using strings and wanted to type neither `std::string` nor `string`? I could use `using` twice to fix this:

```cpp
using std::string; //unnecessary if already using namespace std
using str = string; //use str as an alias for string
```

Or golfed into a single statement:

```cpp
using str = std::string; //str is an alias for std::string directly
```

We can make even more aliases, with even aliases within aliases (see `ll`), for environments where speed is key, such as competitive programming:

```cpp
using namespace std; 
using ll = long long; 
using str = string; 
using pii = pair<int, int>; 
using pll = pair<ll, ll>; 
using vi = vector<int>; 
//warning: avoid these in collaborative projects to avoid headaches
```

Finally, we can take `using` to the next step and invoke templates! For instance, if we want to be able to write `ar<int, 6>` instead of `std::array<int, 6>`, we write:

```cpp
template<class T, int SZ> using ar = std::array<T, SZ>; 
```

As another example, if we want to use `ai` to mean integer array, we can make constructions like `ai<6>` work as well:

```cpp
template<int SZ> using ai = std::array<int, SZ>; 
```

In general, it is important that `using` declarations have strong **scope** guarantees, meaning that they will not work outside of their defined scope. To use declarations everywhere in the program, they must be invoked in global scope. But, if we want to be clever and create a reusable struct and just specify template arguments internally, we always have the option of:

```cpp
struct pt {
    using T = int; 
    //within this scope, T is an alias for int
    //just change this declaration to change T's meaning within this struct
    T x, y, z; 
};
```

In case we want to be able to access the specific type `T`'s alias meaning outside of `pt`, this too becomes very easy:

```cpp
struct pt {
    using T = int; 
    T x, y, z; 
};

int main() {
    using U = pt::T; 
    //U becomes a copy of T from pt's scope
    //U is now in the scope of main
}
```

We end this section off with `#define`. In principle, good code should not need this (because `using` exists), but `#define` is essentially a crude find-and-replace that happens before compile time (in the preprocessor stage). In this sense, it is easy to use, where `#define NAME VALUE` would ideally find all instances of `NAME` in the code and replace them with `VALUE`.   &#x20;

```cpp
#define MOD 1e9 + 7

int main() {
    cout << MOD << "\n"; 
}
```

This example defines `MOD` as `1e9+7` by find and replace. But without resorting to something as crude as `#define`, we could just as well do:&#x20;

```cpp
const int MOD = 1e9 + 7; 

int main() {
    cout << MOD << "\n"; 
}
```

The takeaway is to use `using` and templates and avoid `#define`. If you absolutely insist on using `#define` for some reason, though, use it with caution and remember to `#undef` for good scope control.

### Preprocessing Logic

As far as preprocessor magic goes, we are in no way limited to `#define` butchery. Ever wanted to write a program that compiles in different ways depending on some initial conditions? We can use preprocessor directives like `#if` and `#else`, or `#ifdef` and `#ifndef` to allow for this.&#x20;

For instance, I may want my struct `pt` to be two-dimensional in some cases, and I can control this simply:

```cpp
const bool d2 = 0; //change to true if you want the 2d case; otherwise, 3d

template<class T> struct pt {
    #if(d2)
        T x, y;
    #else
        T x, y, z; 
    #endif
}; 
```

Similarly, if we are not opposed to `#define`, we could use `#ifdef` and `#ifndef` to see whether or not a macro is defined via `#define`.&#x20;

```cpp
//#define 2d //uncomment for 2d 

template<class T> struct pt {
    #ifdef 2d
        T x, y; 
    #else
        T x, y, z; 
    #endif        
}
```

There are many clever applications of this, including versioning. Importantly, if we want code to run differently for different versions of C++, we can write:&#x20;

```cpp
#if(__cplusplus < 201703L)
	template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
		assert(!(hi < lo));
		return (v < lo) ? lo : (hi < v) ? hi : v;
	}
#endif
```

### Namespaces & Inline Namespaces

Finally, we can write our own namespaces to separate various functions. Within a namespace, we can have functions, variables, classes, and even more namespaces. Then, we can invoke `using` declarations to use the whole namespace.&#x20;

```cpp
namespace test {
    const string greeting = "hi"; 
    namespace test1 {
        const int time = 2; 
    } using namespace test1; 
    template<class T> struct my_ds {
        T s;
        void add(T x) { s += x; }
        T get() { return s; } 
    };
}
```

&#x20;These are fairly self-explanatory, but a more rare feature of C++11 is the `inline namespace`. Inline namespaces are not technically real namespaces but allow us to chunk up code and avoid having to use namespaces just to gain access.&#x20;

```cpp
inline namespace test {
    const string greeting = "hi"; 
}
```

So why even have inline namespaces? We can use their features interestingly. For instance, suppose we had a feature in an old version (v1) of a program but now removed it in the new version (v2).&#x20;

```cpp
namespace v1 {
    const string buggy_feature = "bugs"; 
    const string greeting = "hi";    
}

inline namespace v2 {
    //removed the buggy_feature from this new version
    const string buggy_feature = "doesn't exist"; 
    const string greeting = "hi"; 
}

int main() {
    cout << buggy_feature << "\n"; 
    cout << v1::buggy_feature << "\n"; 
}
```

Now, not using a namespace will automatically use v2. But if we want access to v1 of the `buggy_feature`, we can simply write `v1::buggy_feature`. There you have it, simple and effective version control.
