// Properties.cpp #include "Properties.h" #include #include #include #include #include ///////////////////////////////////////////////////////////////////// // Widget class // - test class with a public property class Widget { public: Widget() { std::cout << "\n creating Widget"; } Widget(const Widget& widget) { std::cout << "\n copying Widget"; name = widget.name; } Property name; }; ///////////////////////////////////////////////////////////////////// // CProp alias // - CProp takes a class name C, and supplies // Def, the default getter and setter for classes template using CProp = Property; // default getter and setter for classes ///////////////////////////////////////////////////////////////////// // PProp alias // - PProp

takes a primitive name p, and supplies // PDef, the default getter and setter for primitives template using PProp = Property; // default getter and setter for primitives ///////////////////////////////////////////////////////////////////// // Test class // - test class with class and primitive properties class Test { public: CProp widgetProp; PProp intProp; PProp doubleProp; }; ///////////////////////////////////////////////////////////////////// // putline and putlines // - function aliases std::function putline = []() { std::cout << "\n"; }; std::function putlines = [](size_t n) { for (size_t i = 0; i < n; ++i) std::cout << "\n"; }; ///////////////////////////////////////////////////////////////////// // contents // - global function that returns string of comma separated // values represnting contents of an STL collection template std::string contents(C& c) { std::string content; if (c.size() == 0) return ""; typename C::iterator iter = c.begin(); content.append(*iter); while (++iter != c.end()) { content.append(", "); content.append(*iter); } return content; } ///////////////////////////////////////////////////////////////////// // Test Stub int main() { std::cout << "\n Testing Properties"; std::cout << "\n ===================="; Property sProp = std::string("a string"); std::cout << "\n sProp = " << sProp; std::cout << "\n sProp.size() is " << sProp.size(); Property anotherSProp = std::string("a string"); std::cout << "\n anotherSprop = " << anotherSProp; std::string testStr = sProp; std::cout << "\n testStr = sProp is " << testStr; putline(); std::cout << "\n Testing Properties gets and sets"; std::cout << "\n ----------------------------------"; Test test; Widget widget; widget.name.set("Fred"); test.widgetProp.set(widget); test.intProp.set(3); test.doubleProp.set(3.1415927); std::cout << "\n widget.name = " << widget.name.get(); std::cout << "\n test.widgetProp.name = " << test.widgetProp.get().name.get(); std::cout << "\n test.intProp = " << test.intProp.get(); std::cout << "\n test.doubleProp = " << test.doubleProp.get(); std::cout << "\n 2*test.doubleProp = " << 2 * test.doubleProp.get(); putline(); std::cout << "\n testing property operators: assignment and cast"; std::cout << "\n -------------------------------------------------"; widget.name = "George"; std::cout << "\n widget.name is " << widget.name; std::string widgName = widget.name; std::cout << "\n std::string widgName = widget.name is " << widgName; std::cout << "\n test.widgetProp.name is " << test.widgetProp.name; std::cout << "\n test.widgetProp.name.size() is " << test.widgetProp.name.size(); std::string& testStr2 = test.widgetProp.name; std::cout << "\n std::string& testStr2 = test.widgetProp.name is " << testStr2; testStr2 = "Charley"; std::cout << "\n after setting testStr2 = \"Charley\", test.widgetProp.name is " << test.widgetProp.name; putline(); std::cout << "\n testing Property specializations for int and double"; std::cout << "\n -----------------------------------------------------"; test.intProp = -2; test.doubleProp = 1.0 / 3.0; std::cout << "\n test.intProp is " << test.intProp; int testInt = test.intProp; std::cout << "\n int& testInt = test.intProp is " << testInt; testInt = 4; std::cout << "\n after setting testInt = 4, test.intProp is " << test.intProp; std::cout << "\n test.doubleProp is " << test.doubleProp; Property pi = 3; putline(); std::cout << "\n testing boxed primitives - an alternative to specialization"; std::cout << "\n -------------------------------------------------------------"; Box bInt1 = 1; Box bInt2 = 2; std::cout << "\n bInt1 = " << bInt1; std::cout << "\n bInt2 = " << bInt2; Box bInt3 = 2 * bInt2 + bInt1; std::cout << "\n 2*bInt2 + bInt1 = " << bInt3; using BoxedInt = Box; CProp bIntProp1 = BoxedInt(1); CProp bIntProp2 = BoxedInt(2); CProp bIntProp3; bIntProp3 = bIntProp1 + 2 * bIntProp2; std::cout << "\n bIntProp1 = " << bIntProp1; std::cout << "\n bIntProp2 = " << bIntProp2; std::cout << "\n 2*bIntProp1 + bIntProp2 = " << 2 * bIntProp1 + bIntProp2; CProp> bIntProp4 = Box(2 * bIntProp1 + bIntProp2); std::cout << "\n Box(2 * bIntProp1 + bIntProp2) = " << bIntProp4; putline(); std::cout << "\n testing standard library classes as properties"; std::cout << "\n ------------------------------------------------"; using VecOfStr = std::vector; class Test2 { public: Test2() { sPtrVecOfStr = std::shared_ptr(new VecOfStr); } CProp vecOfStr; CProp> sPtrVecOfStr; }; Test2 test2; VecOfStr vos = { "one", "two", "three" }; test2.vecOfStr = vos; test2.sPtrVecOfStr->push_back("1"); test2.sPtrVecOfStr->push_back("2"); test2.sPtrVecOfStr->push_back("3"); std::cout << "\n test2.vos contains " << contents(test2.vecOfStr); std::cout << "\n test2.sPtrVecOfStr contains " << contents(*test2.sPtrVecOfStr); putline(); std::cout << "\n testing property with revised GS"; std::cout << "\n ----------------------------------"; class TestRevised { public: Property name; }; TestRevised tr; tr.name = "TR's name"; std::cout << "\n tr's name is " << tr.name; putlines(2); return 0; }