//********************************************************
// 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>

class Base
{
 public:
  void callFoo(this auto&& self) { 
    self.foo();    // calls the foo() member for the derived object type
  }
};

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

class D2 : public Base
{ 
 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()
}

