Erased is your constexpr friendly type erasure wrapper type. It is meant to be a fast and easy-to-use C++ type-erasure implementation.
It is heavily inspired by AnyAny.
The tested compilers are:
- MSVC (19.32 and above):
constexpr
does not work since MSVC does not handlevirtual
function in a constexpr context yet. - Clang (19.1 and above)
- GCC (14.1 and above)
Here are the currently supported features
constexpr
friendly- Small Object Optimization
- Copy and
noexcept
move operations - Extendible with multiple behaviors
- Macros helper to remove more and more boilerplate.
- Natural syntax at call site.
Here is an exemple of use:
struct ComputeArea {
constexpr static double invoker(auto &self) { return self.computeArea(); }
// not necessary, but makes the client code easier to write
constexpr double computeArea(this auto &erased) {
return erased.invoke(ComputeArea{});
}
};
struct Perimeter {
constexpr static double invoker(const auto &self) { return self.perimeter(); }
// not necessary, but makes the client code easier to write
constexpr double perimeter(this const auto &erased) {
return erased.invoke(Perimeter{});
}
};
using Surface = erased::erased<ComputeArea, Perimeter>;
void f(const Surface &x) {
double area = x.computeArea();
double perimeter = x.perimeter();
}
Here is the same with macros
ERASED_MAKE_BEHAVIOR(ComputeArea, computeArea,
(&self) requires(self.computeArea())->double);
ERASED_MAKE_BEHAVIOR(Perimeter, perimeter,
(const &self) requires(self.perimeter())->double);
using Surface =
erased::erased<ComputeArea, Perimeter>;
The erased::erased
type has only a constructor and destructor by default. We provide these behaviors to extend easily the given type:
- Copy: Add copy constructor and copy assignment operator
- Move: Add noexcept move constructor and noexcept move assignment operator