summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-12 13:53:48 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-12 13:53:48 +0100
commit8e792d31f499758d3447da46dc85b68356bdbe9b (patch)
treea0545bae9fc9e6c28cf93e449b896e583483bf7f
parentf8775b64f67cc464e024cf79cd98eed30c659d25 (diff)
removed __compare magic method, and added operator< instead
-rw-r--r--documentation/comparing-objects.html169
-rw-r--r--include/base.h10
-rw-r--r--include/class.h6
-rw-r--r--src/base.cpp10
4 files changed, 180 insertions, 15 deletions
diff --git a/documentation/comparing-objects.html b/documentation/comparing-objects.html
new file mode 100644
index 0000000..f5c57a9
--- /dev/null
+++ b/documentation/comparing-objects.html
@@ -0,0 +1,169 @@
+<h1>Comparing objects</h1>
+<p>
+ One of the questions we had to ask ourselves when we developed the PHP-CPP
+ library was whether we should follow PHP conventions or follow C++
+ conventions for many of the library features.
+</p>
+<p>
+ PHP uses <a href="magic-methods">magic methods</a> and
+ <a href="magic-interfaces">magic interfaces</a> to add special behavior to
+ classes. With C++ you can achieve the same, but by using technologies like
+ operator overloading, implicit constructors and casting operators. The
+ PHP __invoke() method for example, is more or less identical to operator ()
+ in C++.
+</p>
+<p>
+ We have decided to follow the PHP conventions, and use magic methods
+ and magic interfaces in C++ as well - although we must admit that having
+ methods that start with two underscores does not make the code very
+ pretty. But by using magic methods the switch from PHP to C++ is kept simpler
+ for starting C++ programmers. And on top of that, not all magic methods and
+ interfaces could have been implemented with core C++ features, so we did have
+ to use <i>some</i> magic methods and/or interfaces anyway.
+</p>
+<p>
+ Besides the magic methods and functions, the Zend engine has additional
+ features that are not exposed via magic methods, and that only are accessible
+ for extension programmers. We have already mentioned that PHP-CPP allows you
+ to implement the __toInteger(), __toFloat() and __toBool() methods (next to
+ the __toString() that can be implemented in PHP scripts too). Another thing
+ that is not available in PHP but that can be used by extensions is the
+ possibility to install a custom object comparison procedure.
+</p>
+<p>
+ If you compare two objects in PHP with comparison operators like &lt; ==, !=
+ &gt; (and some others), the Zend engine runs an object comparison function.
+ The PHP-CPP library interupts this method, and passes the comparison method
+ to the &lt; operator of your class. In other words, if you want to install
+ a custom comparison operator, you can do so by implementing operator&lt;.
+</p>
+<p>
+<pre class="language-c++"><code>
+#include &lt;phpcpp.h&gt;
+/**
+ * A sample class, that shows how objects can be compared
+ */
+class MyClass : public Php::Base
+{
+private:
+ /**
+ * Internal value of the class
+ * @var int
+ */
+ int _value;
+
+public:
+ /**
+ * C++ constructor
+ */
+ MyClass()
+ {
+ // start with random value
+ _value = rand();
+ }
+
+ /**
+ * C++ destructor
+ */
+ virtual ~MyClass() {}
+
+ /**
+ * Cast the object to a string
+ * @return Php::Value
+ */
+ virtual Php::Value __toString() override
+ {
+ return std::to_string(_value);
+ }
+
+ /**
+ * Comparison operator to compare the object
+ * @param that
+ * @return bool
+ */
+ bool operator&lt;(const MyClass &amp;that) const
+ {
+ return _value &lt; that._value;
+ }
+};
+
+/**
+ * Switch to C context to ensure that the get_module() function
+ * is callable by C programs (which the Zend engine is)
+ */
+extern "C" {
+ /**
+ * Startup function that is called by the Zend engine
+ * to retrieve all information about the extension
+ * @return void*
+ */
+ PHPCPP_EXPORT void *get_module() {
+
+ // extension object
+ static Php::Extension myExtension("my_extension", "1.0");
+
+ // description of the class so that PHP knows
+ // which methods are accessible
+ Php::Class&lt;MyClass&gt; myClass("MyClass");
+
+ // add the class to the extension
+ myExtension.add(std::move(myClass));
+
+ // return the extension
+ return myExtension;
+ }
+}
+</code></pre>
+</p>
+<p>
+ The comparison function is automatically called when you try to compare
+ objects in PHP scripts.
+</p>
+<p>
+<pre class="language-php"><code>
+&lt;?php
+// initialize a couple of objects
+$object1 = new MyClass();
+$object2 = new MyClass();
+$object3 = new MyClass();
+
+// compare the objects
+if ($object1 &lt; $object2)
+{
+ echo("$object1 is smaller than $object2\n");
+}
+else
+{
+ echo("$object1 is bigger than $object2\n");
+}
+
+if ($object1 == $object3)
+{
+ echo("$object1 is equal to $object3\n");
+}
+else
+{
+ echo("$object1 is not equal to $object3\n");
+}
+?&gt;
+</code></pre>
+</p>
+<p>
+ The above PHP script could produce the following output:
+</p>
+<p>
+<pre>
+// output
+1699622247 is bigger than 151717746
+1699622247 is not equal to 627198306
+</pre>
+</p>
+<p>
+ Although we have considered to implement this comparison function as a
+ magic method (for example __compare), or as a magic interface (for example
+ Php::Comparable) we have decided to go for the operator&lt; approach that
+ better fits the C++ language. The big advantage of this choice is that your
+ objects can now also be used in many C++ STL algorithms, because they use
+ operator&lt; too.
+</p>
+
diff --git a/include/base.h b/include/base.h
index e99023b..d0e7e71 100644
--- a/include/base.h
+++ b/include/base.h
@@ -220,18 +220,14 @@ public:
virtual bool __toBool();
/**
- * Compare the object with a different object of the same type
+ * Comparison operator
*
- * This method should return 0 if both objects are equal, a negative value
- * if the 'this' object is smaller, and a positive value if the 'this'
- * object is bigger.
- *
- * The passed in object is an instance of base
+ * Check how a different object compares to this object
*
* @param that Object to compare with
* @return int
*/
- virtual bool __compare(const Base &that) const;
+ bool operator<(const Base &that) const;
private:
diff --git a/include/class.h b/include/class.h
index eabcec6..427aa64 100644
--- a/include/class.h
+++ b/include/class.h
@@ -197,7 +197,11 @@ private:
T *t2 = (T *)object2;
// compare the two objects
- return t1->__compare(*t2);
+ if (*t1 < *t2) return -1;
+ if (*t1 > *t2) return 1;
+
+ // they must be identical
+ return 0;
}
/**
diff --git a/src/base.cpp b/src/base.cpp
index a77b30f..516663d 100644
--- a/src/base.cpp
+++ b/src/base.cpp
@@ -256,18 +256,14 @@ bool Base::__toBool()
}
/**
- * Compare the object with a different object of the same type
+ * Comparison operator
*
- * This method should return 0 if both objects are equal, a negative value
- * if the 'this' object is smaller, and a positive value if the 'this'
- * object is bigger.
- *
- * The passed in object is an instance of base
+ * Check how a different object compares to this object
*
* @param that Object to compare with
* @return int
*/
-bool Base::__compare(const Base &that) const
+bool Base::operator<(const Base &that) const
{
// throw an exception that will be caught in the ClassBase class,
// so that the default implementation of the function can be called