//==================================================================== // 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 int main() { std::unique_ptr shape = std::make_unique(); shape->area(); }