//********************************************************
// The following code example is taken from the book
//  C++23 - The Complete Guide
//  by Nicolai M. Josuttis (www.josuttis.com)
//  https://www.cppstd23.com
//
// The code is licensed under a
//  Creative Commons Attribution 4.0 International License
//  https://creativecommons.org/licenses/by/4.0/
//********************************************************


#include <iostream>

template<typename DerivedT>
class Base
{
 public:
  void callFoo() { 
    static_cast<DerivedT*>(this)->foo(); // calls the foo() member for the derived object type 
  }
};

class D1 : public Base<D1>
{ 
 public:
  void foo() {     // foo() of derived type D1
    std::cout << "D1::foo()\n"; 
  }
};

class D2 : public Base<D2>
{ 
 public:
  void foo() {     // foo() of derived type D2
    std::cout << "D2::foo()\n"; 
  }
};

int main()
{
    D1 d1; 
    d1.callFoo();  // calls D1::foo() via Base::callFoo()

    D2 d2; 
    d2.callFoo();  // calls D2::foo() via Base::callFoo()
}

