DEV Community

Daulet Nassipkali
Daulet Nassipkali

Posted on

Harnessing Optional Polymorphism with the Polymorph Class in Platform::Interfaces Library

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. 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:

   [requires]
   platform.interfaces/0.3.41
   [generators]
   CMakeDeps
   CMakeToolchain
Enter fullscreen mode Exit fullscreen mode
  1. Open a terminal in your project directory and run the following command to install the dependencies specified in conanfile.txt:
   conan install .
Enter fullscreen mode Exit fullscreen mode

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:
   find_package(Platform.Interfaces REQUIRED)
Enter fullscreen mode Exit fullscreen mode
  1. Then, link the library to your executable using the target_link_libraries function:
   target_link_libraries(Executable PRIVATE Platform.Interfaces::Platform.Interfaces)
Enter fullscreen mode Exit fullscreen mode
  1. Now, in your C++ source files, you can include the header file of the Platform::Interfaces library as follows:
   #include <Platform.Interfaces.h>
Enter fullscreen mode Exit fullscreen mode

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.

template <typename TSelf, typename... TBase>
class Polymorph : public TBase... {
protected:
  THIS_REFERENCE_WRAPPER_METHODS(object, TSelf)
};
Enter fullscreen mode Exit fullscreen mode

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.

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
  }
};
Enter fullscreen mode Exit fullscreen mode

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():

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

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:

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
  }
};
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)