Harnessing Optional Polymorphism with the Polymorph Class in Platform::Interfaces Library
Tags: cpp, programming, tutorial, learning
Published: 2023-07-14 06:57:54

In object-oriented programming, polymorphism is an essential principle that provides a means to treat objects of various types as objects of a common parent type. Typically, polymorphism comes in two flavors: static and dynamic, each with their own advantages and drawbacks. However, with the `Polymorph` class in the Platform::Interfaces library, we have the possibility of optional polymorphism, a powerful design concept allowing a class to choose between static or dynamic polymorphism, as needed.
### Installing the Platform::Interfaces Library

To make use of the `Polymorph` class and other features provided by the Platform::Interfaces library, you need to install the library in your local development environment. 

Platform::Interfaces is a C++ header-only library, which means that it's composed entirely of header files that are included in your C++ source files at compile time. 

To install the Platform::Interfaces library, we recommend using Conan, a popular open-source package manager for C++.

#### Using Conan for Installation

Here are the steps to install the Platform::Interfaces library with Conan:

1. Install Conan. If you have not installed Conan on your system, you can download it from the [official website](https://conan.io/). Make sure to follow the instructions suitable for your operating system.

2. Create a `conanfile.txt` file in your project directory. This file specifies the dependencies of your project. For the Platform::Interfaces library, your `conanfile.txt` file should look like this:

   ```txt
   [requires]
   platform.interfaces/0.3.41
   [generators]
   CMakeDeps
   CMakeToolchain
   ```

3. Open a terminal in your project directory and run the following command to install the dependencies specified in `conanfile.txt`:

   ```bash
   conan install .
   ```

#### Integrating with CMake

After installing the Platform::Interfaces library with Conan, you can use it in your project. The library integrates with CMake, a cross-platform tool that manages the build process in an operating system-independent manner.

Here are the steps to use the Platform::Interfaces library in your CMake project:

1. In your `CMakeLists.txt` file, use the `find_package` function to locate the Platform::Interfaces library:

   ```cmake
   find_package(Platform.Interfaces REQUIRED)
   ```

2. Then, link the library to your executable using the `target_link_libraries` function:

   ```cmake
   target_link_libraries(Executable PRIVATE Platform.Interfaces::Platform.Interfaces)
   ```

3. Now, in your C++ source files, you can include the header file of the Platform::Interfaces library as follows:

   ```cpp
   #include <Platform.Interfaces.h>
   ```

And that's it! You have successfully installed and set up the Platform::Interfaces library for your project. You can now leverage the power of optional polymorphism with the `Polymorph` class and explore other advanced features provided by the library.
### Optional Polymorphism: The Best of Both Worlds

Optional polymorphism is a powerful design pattern that allows a class to selectively decide between static and dynamic polymorphism. This pattern is useful when you want the compile-time efficiency of static polymorphism while also requiring the flexibility of dynamic polymorphism, which allows for method resolution during runtime.

### Unlocking Optional Polymorphism with Polymorph

The `Polymorph` template class, part of the Platform::Interfaces library, encapsulates optional polymorphism by combining the principles of the Curiously Recurring Template Pattern (CRTP) and traditional polymorphism.

```cpp
template <typename TSelf, typename... TBase>
class Polymorph : public TBase... {
protected:
  THIS_REFERENCE_WRAPPER_METHODS(object, TSelf)
};
```

Located in the "Platform.Interfaces.h" header file, `Polymorph` enables you to specify a set of base classes for a derived class to inherit from. If a base class has virtual functions that aren't entirely overridden in the derived class, `Polymorph` facilitates a combination of static and dynamic polymorphism.

### Delving Deeper: Polymorph in Action

When deriving from `Polymorph`, the derived class acts as a base class, forwarding method calls to further derived classes using the `this->object.method()` convention.

```cpp
class BaseInterface1 {
public:
  virtual void foo() const = 0;  // Pure virtual function
};

class Derived : public Platform::Interfaces::Polymorph<Derived, BaseInterface1> {
public:
  void foo() const {
    this->object().foo();  // Delegation to the next class in the inheritance chain
  }
};
```

Here, `Derived` acts as an intermediary base class, forwarding the method call `foo()` to the next class in the inheritance hierarchy.

Let's see how `Polymorph` enables optional polymorphism through static and dynamic polymorphism. Consider a `FurtherDerived` class that overrides `foo()`:

```cpp
class FurtherDerived : public Derived {
public:
  void foo() const override {
    std::cout << "FurtherDerived::foo() called.\n";  // Dynamic polymorphism
  }
};
```

In this `FurtherDerived` class, `foo()` overrides the pure virtual function from `BaseInterface1`, exemplifying dynamic polymorphism. 

Next, consider a static case where a method `bar()` is introduced:

```cpp
class DerivedStatic : public Platform::Interfaces::Polymorph<DerivedStatic> {
public:
  void bar() const {
    this->object().bar();  // Delegation to the next class in the inheritance chain
  }
};

class FurtherDerivedStatic : public DerivedStatic {
public:
  void bar() const {
    std::cout << "FurtherDerivedStatic::bar() called.\n";  // Static polymorphism
  }
};
```

In this example, `DerivedStatic` serves as the intermediary base class that calls the `bar()` method of the next class in the inheritance chain. Since `bar()` is a non-virtual function in `FurtherDerivedStatic`, it will be resolved at compile time, demonstrating static polymorphism.

### Conclusion

By offering the power of optional polymorphism, the `Polymorph` class in the Platform::Interfaces library empowers developers with the flexibility to determine the type of method resolution (compile-time or runtime) on a per-method basis.

This potent capability, however, demands a solid understanding of advanced C++ concepts including templates, variadic templates, perfect forwarding, type traits, template metaprogramming, multiple inheritance, and polymorphism. As you master these advanced concepts, you'll be able to harness the full potential of `Polymorph` and the entire Platform::Interfaces library.