Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions cpp/Platform.Collections.Methods/Polymorph.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

namespace Platform::Interfaces
{
/// <summary>
/// <para>
/// Represents a base class for implementing the Curiously Recurring Template Pattern (CRTP).
/// This enables static polymorphism where derived classes can be accessed through
/// the base class interface without virtual function overhead.
/// </para>
/// <para>
/// Based on: https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
/// </para>
/// </summary>
/// <typeparam name="TSelf">The derived class type that inherits from this base class.</typeparam>
template <typename TSelf>
class Polymorph
{
protected:
/// <summary>
/// <para>
/// Returns a reference to the derived class object.
/// This method enables static polymorphism by providing access to the
/// actual derived class implementation through a compile-time cast.
/// </para>
/// </summary>
/// <returns>A reference to the derived class object.</returns>
constexpr TSelf& object() noexcept
{
return static_cast<TSelf&>(*this);
}

/// <summary>
/// <para>
/// Returns a const reference to the derived class object.
/// This method enables static polymorphism by providing read-only access to the
/// actual derived class implementation through a compile-time cast.
/// </para>
/// </summary>
/// <returns>A const reference to the derived class object.</returns>
constexpr const TSelf& object() const noexcept
{
return static_cast<const TSelf&>(*this);
}
};
}
Binary file added experiments/test_collections_crtp
Binary file not shown.
67 changes: 67 additions & 0 deletions experiments/test_collections_crtp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <iostream>
#include <cassert>

// Include our CRTP implementation
#include "../cpp/Platform.Collections.Methods/Polymorph.h"

using namespace Platform::Interfaces;

// Simulate the GenericCollectionMethodsBase pattern
template <typename TSelf, typename TElement>
class GenericCollectionMethodsBase : public Polymorph<TSelf>
{
};

// Simulate a DoublyLinkedList methods class
template <typename TSelf, typename TElement>
class DoublyLinkedListMethodsBase : public GenericCollectionMethodsBase<TSelf, TElement>
{
protected:
void IncrementSize()
{
this->object().SetSize(this->object().GetSize() + 1);
}

void DecrementSize()
{
this->object().SetSize(this->object().GetSize() - 1);
}
};

// Concrete implementation that would be provided by user
class MyDoublyLinkedList : public DoublyLinkedListMethodsBase<MyDoublyLinkedList, int>
{
private:
int size = 0;

public:
int GetSize() const { return size; }
void SetSize(int newSize) { size = newSize; }

void TestIncrementDecrement()
{
std::cout << "Initial size: " << GetSize() << std::endl;

IncrementSize();
std::cout << "After increment: " << GetSize() << std::endl;

IncrementSize();
std::cout << "After second increment: " << GetSize() << std::endl;

DecrementSize();
std::cout << "After decrement: " << GetSize() << std::endl;
}
};

int main()
{
std::cout << "Testing Collections CRTP pattern..." << std::endl;

MyDoublyLinkedList list;
list.TestIncrementDecrement();

assert(list.GetSize() == 1);
std::cout << "Final size: " << list.GetSize() << " - Test passed!" << std::endl;

return 0;
}
Binary file added experiments/test_crtp
Binary file not shown.
75 changes: 75 additions & 0 deletions experiments/test_crtp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <iostream>
#include <cassert>

// Include our CRTP implementation
#include "../cpp/Platform.Collections.Methods/Polymorph.h"

using namespace Platform::Interfaces;

// Test class that uses CRTP like the collections classes do
template <typename TSelf>
class TestBase : public Polymorph<TSelf>
{
public:
void DoSomething()
{
std::cout << "Base calling derived method: ";
this->object().Implementation();
}

int GetValue()
{
return this->object().GetValueImpl();
}
};

// Derived class that implements the interface
class TestDerived : public TestBase<TestDerived>
{
public:
void Implementation()
{
std::cout << "TestDerived::Implementation() called!" << std::endl;
}

int GetValueImpl()
{
return 42;
}
};

// Another derived class to test polymorphism
class AnotherDerived : public TestBase<AnotherDerived>
{
public:
void Implementation()
{
std::cout << "AnotherDerived::Implementation() called!" << std::endl;
}

int GetValueImpl()
{
return 100;
}
};

int main()
{
std::cout << "Testing CRTP (Curiously Recurring Template Pattern) implementation..." << std::endl;

// Test TestDerived
TestDerived derived1;
derived1.DoSomething();
assert(derived1.GetValue() == 42);
std::cout << "TestDerived value: " << derived1.GetValue() << std::endl;

// Test AnotherDerived
AnotherDerived derived2;
derived2.DoSomething();
assert(derived2.GetValue() == 100);
std::cout << "AnotherDerived value: " << derived2.GetValue() << std::endl;

std::cout << "All tests passed! CRTP implementation is working correctly." << std::endl;

return 0;
}
Loading