Skip to content

Curve/eraser

Repository files navigation


A C++20 type-erasure library that supports interfaces


👋 Introduction

Eraser is an easy, customizable, C++20 type-erasure library that supports user defined interfaces.

📦 Installation

  • Using CPM

    CPMFindPackage(
      NAME           eraser
      VERSION        2.2.1
      GIT_REPOSITORY "https://github.com/Curve/eraser"
    )
  • Using FetchContent

    include(FetchContent)
    
    FetchContent_Declare(eraser GIT_REPOSITORY "https://github.com/Curve/eraser" GIT_TAG v2.2.1)
    FetchContent_MakeAvailable(eraser)
    
    target_link_libraries(<target> cr::eraser)

📖 Examples

Given two classes erase_me and erase_me_too:

struct erase_me
{
int *target;
public:
[[nodiscard]] int a() const
{
return (*target = 10);
}
static double b(int &target)
{
target = 20;
return 3.14;
}
};
struct erase_me_too
{
std::reference_wrapper<int> target;
public:
[[nodiscard]] int a() const
{
return (target.get() = 30);
}
static double b(int &target)
{
target = 40;
return 2.71;
}
};

There are two ways to "erase" them:

...the normal approach:

eraser/tests/erased.cpp

Lines 13 to 22 in b61dc0f

enum class methods
{
a,
b,
};
using interface = eraser::interface< //
method<methods::a, [](auto &self) { return self.a(); }, int()>, //
method<methods::b, [](auto &self, int &target) { return self.b(target); }, double(int &)> //
>;

eraser/tests/erased.cpp

Lines 27 to 36 in b61dc0f

int target{};
auto e1 = make_erased<interface, erase_me>(&target);
erased<interface> e2{erase_me_too{std::ref(target)}};
expect(eq(e1.invoke<methods::a>(), 10));
expect(eq(target, 10));
expect(eq(e2.invoke<methods::a>(), 30));
expect(eq(target, 30));

... or the experimental/"hacky" approach:

eraser/tests/deduce.cpp

Lines 9 to 20 in b61dc0f

struct interface
{
int a()
{
return eraser::experimental::call<int>([](auto &self) { return self.a(); }, this);
}
double b(int &target)
{
return eraser::experimental::call<double>([](auto &self, int &target) { return self.b(target); }, this, target);
}
};

eraser/tests/deduce.cpp

Lines 29 to 38 in b61dc0f

int target{};
auto e1 = make_erased<deduce<interface>, erase_me>(&target);
erased<deduce<interface>> e2{erase_me_too{std::ref(target)}};
expect(eq(e1.a(), 10));
expect(eq(target, 10));
expect(eq(e2.a(), 30));
expect(eq(target, 30));


While the "hacky" approach might look more pleasing, you should prefer to use the normal approach. As the name implies, the hacky approach relies on friend injection which allows one to do stateful meta-programming, which is technically not legal C++, however, all three major compilers support it.

⭐ Credits

About

✏️ A C++20 type-erasure library

Topics

Resources

License

Stars

Watchers

Forks

Contributors