blob: 1af545545cf7962cd0e1262cd6f053896de57200 [file] [log] [blame] [raw]
//====================================================================
// Library code: implementing the metaclass (once)
$class interface {
constexpr {
compiler.require($interface.variables().empty(),
"interfaces may not contain data");
for... (auto f : $interface.functions()) {
compiler.require(!f.is_copy() && !f.is_move(),
"interfaces may not copy or move; consider a"
" virtual clone() instead");
if (!f.has_access()) f.make_public();
compiler.require(f.is_public(),
"interface functions must be public");
f.make_pure_virtual();
}
}
virtual ~interface() noexcept { }
};
//====================================================================
// User code: using the metaclass to write a type (many times)
interface Shape {
int area() const;
void scale_by(double factor);
};
// try putting any of these lines into Shape to see "interface" rules
// enforced => using the metaclass name to declare intent makes
// this code more robust to such changes under maintenance
//
// int i; // error: interfaces may not contain data
// private: void g(); // error: interface functions must be public
// Shape(const Shape&); // error: interfaces may not copy or move;
// // consider a virtual clone() instead
// Godbolt.org note: Click the "triangle ! icon" to see the output
constexpr {
compiler.debug($Shape);
}
//====================================================================
// And then continue to use it as "just a class" as always... this is
// normal code just as if we'd written Shape not using a metaclass
class Circle : public Shape {
public:
int area() const override { return 1; }
void scale_by(double factor) override { }
};
#include <memory>
int main() {
std::unique_ptr<Shape> shape = std::make_unique<Circle>();
shape->area();
}