diff --git a/examples/cppx/Interface.cpp b/examples/cppx/Interface.cpp index 1af545545..85e7ab57c 100644 --- a/examples/cppx/Interface.cpp +++ b/examples/cppx/Interface.cpp @@ -1,29 +1,36 @@ +#include +#include + +using namespace std::experimental; //==================================================================== // 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 { } +consteval void interface(meta::info source) { + for (meta::info mem : meta::member_range(source)) { + meta::compiler.require(!meta::is_data_member(mem), "interfaces may not contain data"); + meta::compiler.require(!meta::is_copy(mem) && !meta::is_move(mem), + "interfaces may not copy or move; consider" + " a virtual clone() instead"); + + if (meta::has_default_access(mem)) + meta::make_public(mem); + + meta::compiler.require(meta::is_public(mem), "interface functions must be public"); + + meta::make_pure_virtual(mem); + + -> mem; + } + + -> fragment struct X { virtual ~X() noexcept {} }; }; //==================================================================== // User code: using the metaclass to write a type (many times) -interface Shape { +class(interface) Shape { int area() const; void scale_by(double factor); }; @@ -37,12 +44,10 @@ interface Shape { // 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); +consteval { + meta::compiler.print(reflexpr(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 @@ -53,6 +58,10 @@ public: void scale_by(double factor) override { } }; +consteval { + meta::compiler.print(reflexpr(Circle)); +} + #include int main() { diff --git a/examples/cppx/Interface_(CppCon_2017).cpp b/examples/cppx/Interface_(CppCon_2017).cpp new file mode 100644 index 000000000..1af545545 --- /dev/null +++ b/examples/cppx/Interface_(CppCon_2017).cpp @@ -0,0 +1,61 @@ + +//==================================================================== +// 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(); +} diff --git a/examples/cppx/Value_(CppCon_2017).cpp b/examples/cppx/Value_(CppCon_2017).cpp new file mode 100644 index 000000000..503cffe41 --- /dev/null +++ b/examples/cppx/Value_(CppCon_2017).cpp @@ -0,0 +1,47 @@ +//==================================================================== +// Library code: implementing the metaclass (once) + +$class basic_value { + basic_value() = default; + basic_value(const basic_value& that) = default; + basic_value(basic_value&& that) = default; + basic_value& operator=(const basic_value& that) = default; + basic_value& operator=(basic_value&& that) = default; + + constexpr { + for... (auto f : $basic_value.variables()) + if (!f.has_access()) f.make_private(); + for... (auto f : $basic_value.functions()) { + if (!f.has_access()) f.make_public(); + compiler.require(!f.is_protected(), "a value type may not have a protected function"); + compiler.require(!f.is_virtual(), "a value type may not have a virtual function"); + compiler.require(!f.is_destructor() || f.is_public(), "a value destructor must be public"); + } + } +}; + +$class value : basic_value { }; + + +//==================================================================== +// User code: using the metaclass to write a type (many times) + +value Point { + int x = 0, y = 0; + Point(int xx, int yy) : x{xx}, y{yy} { } +}; + +Point get_some_point() { return {1,1}; } + +int main() { + + Point p1(50,100), p2; + p2 = get_some_point(); + p2.x = 42; + +} + +// Compiler Explorer note: Click the "triangle ! icon" to see the output: +constexpr { + compiler.debug($Point); +} diff --git a/examples/cppx/default.cpp b/examples/cppx/default.cpp index 503cffe41..3e1d904d2 100644 --- a/examples/cppx/default.cpp +++ b/examples/cppx/default.cpp @@ -1,47 +1,2 @@ -//==================================================================== -// Library code: implementing the metaclass (once) - -$class basic_value { - basic_value() = default; - basic_value(const basic_value& that) = default; - basic_value(basic_value&& that) = default; - basic_value& operator=(const basic_value& that) = default; - basic_value& operator=(basic_value&& that) = default; - - constexpr { - for... (auto f : $basic_value.variables()) - if (!f.has_access()) f.make_private(); - for... (auto f : $basic_value.functions()) { - if (!f.has_access()) f.make_public(); - compiler.require(!f.is_protected(), "a value type may not have a protected function"); - compiler.require(!f.is_virtual(), "a value type may not have a virtual function"); - compiler.require(!f.is_destructor() || f.is_public(), "a value destructor must be public"); - } - } -}; - -$class value : basic_value { }; - - -//==================================================================== -// User code: using the metaclass to write a type (many times) - -value Point { - int x = 0, y = 0; - Point(int xx, int yy) : x{xx}, y{yy} { } -}; - -Point get_some_point() { return {1,1}; } - -int main() { - - Point p1(50,100), p2; - p2 = get_some_point(); - p2.x = 42; - -} - -// Compiler Explorer note: Click the "triangle ! icon" to see the output: -constexpr { - compiler.debug($Point); -} +// Pick an appropriate example from the Load/Save +// icon above.