lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master 60e0657 1/5: Experimentally implement certain


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 60e0657 1/5: Experimentally implement certain compound assignment operators
Date: Sun, 21 Mar 2021 21:10:52 -0400 (EDT)

branch: master
commit 60e06577fd28d7352a6a68952be2feaecfbebe50
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Experimentally implement certain compound assignment operators
    
    For PETE with std::vector, overloading std::vector::operator=() to
    take a PETE Expression argument is not permitted because operator=()
    must be a member, and altering namespace std is generally forbidden.
    However, this:
      assign(std::vector<T> lhs, Expression<T>);
    is ugly and cumbersome.
    
    It is permitted to overload compound assignment operators because
    they needn't be members. Two are implemented here, experimentally:
    
      operator<<(): This is somewhat reminiscent of stream inserters.
      It cannot clash with PETE because PETE normally avoids defining
      shift operators.
    
      operator<<=(): This is also somewhat reminiscent of stream inserters,
      yet is clearly an assignment operator. Compared to operator<<(), it
      has an even lower precedence, which is an important advantage; it
      requires typing an extra character; and it looks weirder, but that's
      an advantage because it tells newcomers they'd better look it up in
      lmi's documentation. It seems to work without modifying PETE (perhaps
      because this implementation is more specialized?), but it would be
      better to excise shift-assignment operators from PETE.
    
      operator^=() (not implemented): This would be one character shorter
      than operator<<=(), but that seems to be the only point in its favor.
      Its connotation is more confusing: there's no operator^(std::ostream&)
      to suggest at any unusual meaning, and outside of C++ '^' suggests
      exponentiation.
    
    In light of those advantages and disadvantages, operator<<=() seems
    preferable.
    
    See 'expression_template_0_test.cpp' for an earlier experiment.
---
 et_vector_test.cpp | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/et_vector_test.cpp b/et_vector_test.cpp
index fd8daa3..8a86b09 100644
--- a/et_vector_test.cpp
+++ b/et_vector_test.cpp
@@ -25,6 +25,26 @@
 
 #include <functional>                   // multiplies(), negate(), plus()
 
+// Experimental operators.
+//
+// See 'expression_template_0_test.cpp' for an earlier implementation
+// of operator<<().
+
+template<typename T, typename U>
+inline std::vector<T>& operator<<(std::vector<T>& t, Expression<U> const& u)
+{
+#if defined PETE_ALLOW_SCALAR_SHIFT
+#   error PETE_ALLOW_SCALAR_SHIFT must not be defined.
+#endif // defined PETE_ALLOW_SCALAR_SHIFT
+    return assign(t, u);
+}
+
+template<typename T, typename U>
+inline std::vector<T>& operator<<=(std::vector<T>& t, Expression<U> const& u)
+{
+    return t = Eval(u);
+}
+
 int test_main(int, char*[])
 {
     {
@@ -66,6 +86,21 @@ int test_main(int, char*[])
     LMI_TEST(r1 == y);
     }
 
+    // Test experimental operator<<() and operator<<=().
+    {
+    std::vector<double> v0 = {1.0, 1.25, 1.5};
+    std::vector<double> v1 = {0.0, 0.25, 0.5};
+    std::vector<double> x(3);
+//  assign(x, v0 + v1);
+    x << v0 + v1;
+    std::vector<double> y(3);
+    y <<= v0 + v1 + x;
+    std::vector<double> const r0 = {1.0, 1.5, 2.0};
+    LMI_TEST(r0 == x);
+    std::vector<double> const r1 = {2.0, 3.0, 4.0};
+    LMI_TEST(r1 == y);
+    }
+
     // Test peteCast().
     {
     std::vector<double> v0 = {0.0, 1.25, 2.5};



reply via email to

[Prev in Thread] Current Thread [Next in Thread]