This is an automated email from the ASF dual-hosted git repository.

westonpace pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 79563cf2f7 GH-15098: [C++] fix util::EqualityComparable to compile on 
clang 15 (#33940)
79563cf2f7 is described below

commit 79563cf2f798f071e45c3154738388e821b2b02e
Author: Weston Pace <[email protected]>
AuthorDate: Thu Feb 16 20:16:27 2023 -0800

    GH-15098: [C++] fix util::EqualityComparable to compile on clang 15 (#33940)
    
    If you have an equality operator then C++20 then clang 15 expects it to be 
symmetric.  The util::EqualityComparable operator== was defined as:
    
    `bool operator==(util::EqualityComparable<T>, T)`
    
    and there is no equivalent:
    
    `bool operator==(T, util::EqualityComparable<T>)`
    
    This was later determined to be unintentional strictness and the [standard 
was 
clarified](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2468r2.html).
  This error was relaxed in clang 16.  Equality only needs to be symmetric if 
you want the compiler to provide `!=` for you (which we don't rely on).  
However, it seems like a worthwhile fix, and it doesn't appear that Clang will 
be backporting the fix to clang 15 (that is my interpretation of the fact that 
clang lists the def [...]
    
    Furthermore, the old definition allowed for 
`Scalar::operator==(std::shared_ptr<Scalar> other)` (i.e. comparing with a 
shared_ptr) and it isn't clear to me that should be allowed (it's generally 
inconsistent with the rest of the code base).  This change seems to have undone 
that and I made no change to restore it (and instead fixed the references to 
that odd equality operation).
    
    BREAKING CHANGE: The functions `bool Scalar::Equals(const 
std::shared_ptr<Scalar>&) const` and `bool Scalar::Equals(const 
std::shared_ptr<Scalar>&, const  EqualOptions&) const` have been removed.  
Instead `bool Scalar::Equals(const Scalar&) const` and `bool 
Scalar::Equals(const Scalar&, const EqualOptions&) const` should be used.
    
    BREAKING CHANGE: `FileInfo::ToString` now includes the size and mtime.
    
    * Closes: #15098
    
    Authored-by: Weston Pace <[email protected]>
    Signed-off-by: Weston Pace <[email protected]>
---
 c_glib/arrow-glib/scalar.cpp               |  4 +-
 c_glib/test/test-file-info.rb              |  2 +-
 cpp/src/arrow/compute/api_vector.h         |  3 --
 cpp/src/arrow/compute/exec/expression.cc   |  4 +-
 cpp/src/arrow/compute/exec/source_node.cc  |  2 +-
 cpp/src/arrow/compute/function.h           |  3 --
 cpp/src/arrow/compute/kernels/test_util.cc |  2 +-
 cpp/src/arrow/dataset/file_parquet.cc      |  2 +-
 cpp/src/arrow/filesystem/filesystem.cc     |  3 +-
 cpp/src/arrow/filesystem/gcsfs_test.cc     |  8 +---
 cpp/src/arrow/scalar.h                     |  2 -
 cpp/src/arrow/scalar_test.cc               | 76 +++++++++++++++---------------
 cpp/src/arrow/testing/json_integration.cc  |  2 +-
 cpp/src/arrow/testing/matchers.h           |  4 +-
 cpp/src/arrow/util/compare.h               |  6 +--
 r/src/scalar.cpp                           |  2 +-
 16 files changed, 58 insertions(+), 67 deletions(-)

diff --git a/c_glib/arrow-glib/scalar.cpp b/c_glib/arrow-glib/scalar.cpp
index 24f9b2caad..401d0b6dfb 100644
--- a/c_glib/arrow-glib/scalar.cpp
+++ b/c_glib/arrow-glib/scalar.cpp
@@ -340,10 +340,10 @@ garrow_scalar_equal_options(GArrowScalar *scalar,
     if (is_approx) {
       return arrow_scalar->ApproxEquals(*arrow_other_scalar, *arrow_options);
     } else {
-      return arrow_scalar->Equals(arrow_other_scalar, *arrow_options);
+      return arrow_scalar->Equals(*arrow_other_scalar, *arrow_options);
     }
   } else {
-    return arrow_scalar->Equals(arrow_other_scalar);
+    return arrow_scalar->Equals(*arrow_other_scalar);
   }
 }
 
diff --git a/c_glib/test/test-file-info.rb b/c_glib/test/test-file-info.rb
index e6a3a0d62a..64633e2e67 100644
--- a/c_glib/test/test-file-info.rb
+++ b/c_glib/test/test-file-info.rb
@@ -164,7 +164,7 @@ class TestFileInfo < Test::Unit::TestCase
   end
 
   test("#to_s") do
-    assert_equal("FileInfo(FileType::Unknown, )",
+    assert_equal("FileInfo(FileType::Unknown, , -1, -1)",
                  @file_info.to_s)
   end
 end
diff --git a/cpp/src/arrow/compute/api_vector.h 
b/cpp/src/arrow/compute/api_vector.h
index 88331b6e59..365ca0a684 100644
--- a/cpp/src/arrow/compute/api_vector.h
+++ b/cpp/src/arrow/compute/api_vector.h
@@ -101,9 +101,6 @@ class ARROW_EXPORT SortKey : public 
util::EqualityComparable<SortKey> {
   explicit SortKey(FieldRef target, SortOrder order = SortOrder::Ascending)
       : target(std::move(target)), order(order) {}
 
-  using util::EqualityComparable<SortKey>::Equals;
-  using util::EqualityComparable<SortKey>::operator==;
-  using util::EqualityComparable<SortKey>::operator!=;
   bool Equals(const SortKey& other) const;
   std::string ToString() const;
 
diff --git a/cpp/src/arrow/compute/exec/expression.cc 
b/cpp/src/arrow/compute/exec/expression.cc
index 4d060f34e3..b5e5bf6038 100644
--- a/cpp/src/arrow/compute/exec/expression.cc
+++ b/cpp/src/arrow/compute/exec/expression.cc
@@ -225,7 +225,7 @@ bool Expression::Equals(const Expression& other) const {
     // is equal to the literal NaN (e.g. the expressions are equal even if
     // the values are not)
     EqualOptions equal_options = EqualOptions::Defaults().nans_equal(true);
-    return lit->scalar()->Equals(other.literal()->scalar(), equal_options);
+    return lit->scalar()->Equals(*other.literal()->scalar(), equal_options);
   }
 
   if (auto ref = field_ref()) {
@@ -248,7 +248,7 @@ bool Expression::Equals(const Expression& other) const {
 
   if (call->options == other_call->options) return true;
   if (call->options && other_call->options) {
-    return call->options->Equals(other_call->options);
+    return call->options->Equals(*other_call->options);
   }
   return false;
 }
diff --git a/cpp/src/arrow/compute/exec/source_node.cc 
b/cpp/src/arrow/compute/exec/source_node.cc
index 426063a3c1..5be35f3360 100644
--- a/cpp/src/arrow/compute/exec/source_node.cc
+++ b/cpp/src/arrow/compute/exec/source_node.cc
@@ -86,7 +86,7 @@ struct SourceNode : ExecNode, public TracedNode {
       batch_count_ += num_batches;
     }
     plan_->query_context()->ScheduleTask(
-        [=]() {
+        [this, morsel_length, use_legacy_batching, morsel]() {
           int64_t offset = 0;
           do {
             int64_t batch_size =
diff --git a/cpp/src/arrow/compute/function.h b/cpp/src/arrow/compute/function.h
index 8a1b0da424..333c9a65c5 100644
--- a/cpp/src/arrow/compute/function.h
+++ b/cpp/src/arrow/compute/function.h
@@ -65,9 +65,6 @@ class ARROW_EXPORT FunctionOptions : public 
util::EqualityComparable<FunctionOpt
   const char* type_name() const { return options_type()->type_name(); }
 
   bool Equals(const FunctionOptions& other) const;
-  using util::EqualityComparable<FunctionOptions>::Equals;
-  using util::EqualityComparable<FunctionOptions>::operator==;
-  using util::EqualityComparable<FunctionOptions>::operator!=;
   std::string ToString() const;
   std::unique_ptr<FunctionOptions> Copy() const;
   /// \brief Serialize an options struct to a buffer.
diff --git a/cpp/src/arrow/compute/kernels/test_util.cc 
b/cpp/src/arrow/compute/kernels/test_util.cc
index 9341c35b1a..23d0fd18d5 100644
--- a/cpp/src/arrow/compute/kernels/test_util.cc
+++ b/cpp/src/arrow/compute/kernels/test_util.cc
@@ -85,7 +85,7 @@ void CheckScalar(std::string func_name, const ScalarVector& 
inputs,
                  std::shared_ptr<Scalar> expected, const FunctionOptions* 
options) {
   ASSERT_OK_AND_ASSIGN(Datum out, CallFunction(func_name, GetDatums(inputs), 
options));
   ValidateOutput(out);
-  if (!out.scalar()->Equals(expected)) {
+  if (!out.scalar()->Equals(*expected)) {
     std::string summary = func_name + "(";
     for (const auto& input : inputs) {
       summary += input->ToString() + ",";
diff --git a/cpp/src/arrow/dataset/file_parquet.cc 
b/cpp/src/arrow/dataset/file_parquet.cc
index 2ea6f76784..3a9931cf2a 100644
--- a/cpp/src/arrow/dataset/file_parquet.cc
+++ b/cpp/src/arrow/dataset/file_parquet.cc
@@ -303,7 +303,7 @@ std::optional<compute::Expression> 
ParquetFileFragment::EvaluateStatisticsAsExpr
     min = maybe_min.MoveValueUnsafe();
     max = maybe_max.MoveValueUnsafe();
 
-    if (min->Equals(max)) {
+    if (min->Equals(*max)) {
       auto single_value = compute::equal(field_expr, 
compute::literal(std::move(min)));
 
       if (statistics.null_count() == 0) {
diff --git a/cpp/src/arrow/filesystem/filesystem.cc 
b/cpp/src/arrow/filesystem/filesystem.cc
index c8fa4d1c37..73b94d3828 100644
--- a/cpp/src/arrow/filesystem/filesystem.cc
+++ b/cpp/src/arrow/filesystem/filesystem.cc
@@ -116,7 +116,8 @@ std::string FileInfo::ToString() const {
 }
 
 std::ostream& operator<<(std::ostream& os, const FileInfo& info) {
-  return os << "FileInfo(" << info.type() << ", " << info.path() << ")";
+  return os << "FileInfo(" << info.type() << ", " << info.path() << ", " << 
info.size()
+            << ", " << info.mtime().time_since_epoch().count() << ")";
 }
 
 std::string FileInfo::extension() const {
diff --git a/cpp/src/arrow/filesystem/gcsfs_test.cc 
b/cpp/src/arrow/filesystem/gcsfs_test.cc
index af22087530..15d596dc0b 100644
--- a/cpp/src/arrow/filesystem/gcsfs_test.cc
+++ b/cpp/src/arrow/filesystem/gcsfs_test.cc
@@ -46,7 +46,6 @@
 #include <gtest/gtest.h>
 
 #include <array>
-#include <iostream>
 #include <random>
 #include <string>
 #include <thread>
@@ -61,10 +60,6 @@
 
 namespace arrow {
 namespace fs {
-/// Custom comparison for FileInfo, we need this to use complex googletest 
matchers.
-inline bool operator==(const FileInfo& a, const FileInfo& b) {
-  return a.path() == b.path() && a.type() == b.type();
-}
 
 namespace {
 
@@ -268,7 +263,8 @@ class GcsIntegrationTest : public ::testing::Test {
         const auto filename =
             internal::ConcatAbstractPath(folder, "test-file-" + 
std::to_string(i));
         CreateFile(fs.get(), filename, filename);
-        result.contents.push_back(arrow::fs::File(filename));
+        ARROW_ASSIGN_OR_RAISE(auto file_info, fs->GetFileInfo(filename));
+        result.contents.push_back(std::move(file_info));
       }
     }
     return result;
diff --git a/cpp/src/arrow/scalar.h b/cpp/src/arrow/scalar.h
index cf852dff36..a6c959c4d9 100644
--- a/cpp/src/arrow/scalar.h
+++ b/cpp/src/arrow/scalar.h
@@ -60,8 +60,6 @@ struct ARROW_EXPORT Scalar : public 
std::enable_shared_from_this<Scalar>,
   /// \brief Whether the value is valid (not null) or not
   bool is_valid = false;
 
-  using util::EqualityComparable<Scalar>::operator==;
-  using util::EqualityComparable<Scalar>::Equals;
   bool Equals(const Scalar& other,
               const EqualOptions& options = EqualOptions::Defaults()) const;
 
diff --git a/cpp/src/arrow/scalar_test.cc b/cpp/src/arrow/scalar_test.cc
index 404bbc84c5..5c2f1f1e3b 100644
--- a/cpp/src/arrow/scalar_test.cc
+++ b/cpp/src/arrow/scalar_test.cc
@@ -437,10 +437,10 @@ class TestDecimalScalar : public ::testing::Test {
     ASSERT_OK(first->ValidateFull());
     ASSERT_OK(second->ValidateFull());
 
-    ASSERT_TRUE(first->Equals(null));
+    ASSERT_TRUE(first->Equals(*null));
     ASSERT_FALSE(first->Equals(pi));
     ASSERT_TRUE(second->Equals(pi));
-    ASSERT_FALSE(second->Equals(null));
+    ASSERT_FALSE(second->Equals(*null));
 
     auto invalid = ScalarType(ValueType::GetMaxValue(6), 
std::make_shared<T>(5, 2));
     EXPECT_RAISES_WITH_MESSAGE_THAT(Invalid,
@@ -556,7 +556,7 @@ class TestStringScalar : public ::testing::Test {
     ASSERT_OK(one->ValidateFull());
     ASSERT_OK(two->ValidateFull());
 
-    ASSERT_TRUE(null->Equals(CheckMakeNullScalar(type_)));
+    ASSERT_TRUE(null->Equals(*CheckMakeNullScalar(type_)));
     ASSERT_TRUE(one->Equals(ScalarType("one")));
     ASSERT_TRUE(two->Equals(ScalarType("two")));
     ASSERT_FALSE(two->Equals(Int64Scalar(1)));
@@ -632,7 +632,7 @@ TEST(TestFixedSizeBinaryScalar, Basics) {
   ASSERT_OK(one->ValidateFull());
   ASSERT_OK(two->ValidateFull());
 
-  ASSERT_TRUE(null->Equals(CheckMakeNullScalar(ty)));
+  ASSERT_TRUE(null->Equals(*CheckMakeNullScalar(ty)));
   ASSERT_TRUE(one->Equals(FixedSizeBinaryScalar(Buffer::FromString("one"), 
ty)));
   ASSERT_TRUE(two->Equals(FixedSizeBinaryScalar(Buffer::FromString("two"), 
ty)));
 }
@@ -695,10 +695,10 @@ TEST(TestDateScalars, Basics) {
     ASSERT_OK(null->ValidateFull());
     ASSERT_OK(last->ValidateFull());
 
-    ASSERT_TRUE(null->Equals(CheckMakeNullScalar(ty)));
-    ASSERT_TRUE(first->Equals(MakeScalar(ty, 5).ValueOrDie()));
-    ASSERT_TRUE(last->Equals(MakeScalar(ty, 42).ValueOrDie()));
-    ASSERT_FALSE(last->Equals(MakeScalar("string")));
+    ASSERT_TRUE(null->Equals(*CheckMakeNullScalar(ty)));
+    ASSERT_TRUE(first->Equals(*MakeScalar(ty, 5).ValueOrDie()));
+    ASSERT_TRUE(last->Equals(*MakeScalar(ty, 42).ValueOrDie()));
+    ASSERT_FALSE(last->Equals(*MakeScalar("string")));
   }
 }
 
@@ -751,10 +751,10 @@ TEST(TestTimeScalars, Basics) {
     ASSERT_OK(null->ValidateFull());
     ASSERT_OK(last->ValidateFull());
 
-    ASSERT_TRUE(null->Equals(CheckMakeNullScalar(ty)));
-    ASSERT_TRUE(first->Equals(MakeScalar(ty, 5).ValueOrDie()));
-    ASSERT_TRUE(last->Equals(MakeScalar(ty, 42).ValueOrDie()));
-    ASSERT_FALSE(last->Equals(MakeScalar("string")));
+    ASSERT_TRUE(null->Equals(*CheckMakeNullScalar(ty)));
+    ASSERT_TRUE(first->Equals(*MakeScalar(ty, 5).ValueOrDie()));
+    ASSERT_TRUE(last->Equals(*MakeScalar(ty, 42).ValueOrDie()));
+    ASSERT_FALSE(last->Equals(*MakeScalar("string")));
   }
 }
 
@@ -819,10 +819,10 @@ TEST(TestTimestampScalars, Basics) {
     ASSERT_OK(null->ValidateFull());
     ASSERT_OK(last->ValidateFull());
 
-    ASSERT_TRUE(null->Equals(CheckMakeNullScalar(ty)));
-    ASSERT_TRUE(first->Equals(MakeScalar(ty, 5).ValueOrDie()));
-    ASSERT_TRUE(last->Equals(MakeScalar(ty, 42).ValueOrDie()));
-    ASSERT_FALSE(last->Equals(MakeScalar(int64(), 42).ValueOrDie()));
+    ASSERT_TRUE(null->Equals(*CheckMakeNullScalar(ty)));
+    ASSERT_TRUE(first->Equals(*MakeScalar(ty, 5).ValueOrDie()));
+    ASSERT_TRUE(last->Equals(*MakeScalar(ty, 42).ValueOrDie()));
+    ASSERT_FALSE(last->Equals(*MakeScalar(int64(), 42).ValueOrDie()));
   }
 }
 
@@ -909,9 +909,9 @@ TEST(TestDurationScalars, Basics) {
     ASSERT_OK(null->ValidateFull());
     ASSERT_OK(last->ValidateFull());
 
-    ASSERT_TRUE(null->Equals(CheckMakeNullScalar(ty)));
-    ASSERT_TRUE(first->Equals(MakeScalar(ty, 5).ValueOrDie()));
-    ASSERT_TRUE(last->Equals(MakeScalar(ty, 42).ValueOrDie()));
+    ASSERT_TRUE(null->Equals(*CheckMakeNullScalar(ty)));
+    ASSERT_TRUE(first->Equals(*MakeScalar(ty, 5).ValueOrDie()));
+    ASSERT_TRUE(last->Equals(*MakeScalar(ty, 42).ValueOrDie()));
   }
 
   EXPECT_EQ(DurationScalar{std::chrono::nanoseconds{1235}},
@@ -972,9 +972,9 @@ TEST(TestMonthIntervalScalars, Basics) {
   ASSERT_OK(null->ValidateFull());
   ASSERT_OK(last->ValidateFull());
 
-  ASSERT_TRUE(null->Equals(CheckMakeNullScalar(type)));
-  ASSERT_TRUE(first->Equals(MakeScalar(type, 5).ValueOrDie()));
-  ASSERT_TRUE(last->Equals(MakeScalar(type, 42).ValueOrDie()));
+  ASSERT_TRUE(null->Equals(*CheckMakeNullScalar(type)));
+  ASSERT_TRUE(first->Equals(*MakeScalar(type, 5).ValueOrDie()));
+  ASSERT_TRUE(last->Equals(*MakeScalar(type, 42).ValueOrDie()));
 }
 
 TEST(TestDayTimeIntervalScalars, Basics) {
@@ -1164,8 +1164,8 @@ TEST(TestStructScalar, FieldAccess) {
   ASSERT_RAISES(Invalid, abc.field("c").status());
 
   ASSERT_OK_AND_ASSIGN(auto d, abc.field("d"));
-  ASSERT_TRUE(d->Equals(MakeNullScalar(int64())));
-  ASSERT_FALSE(d->Equals(MakeScalar(int64(), 12).ValueOrDie()));
+  ASSERT_TRUE(d->Equals(*MakeNullScalar(int64())));
+  ASSERT_FALSE(d->Equals(*MakeScalar(int64(), 12).ValueOrDie()));
 }
 
 TEST(TestStructScalar, NullScalar) {
@@ -1269,25 +1269,25 @@ TEST(TestDictionaryScalar, Basics) {
         auto encoded_null,
         checked_cast<const DictionaryScalar&>(*scalar_null).GetEncodedValue());
     ASSERT_OK(encoded_null->ValidateFull());
-    ASSERT_TRUE(encoded_null->Equals(MakeNullScalar(utf8())));
+    ASSERT_TRUE(encoded_null->Equals(*MakeNullScalar(utf8())));
 
     ASSERT_OK_AND_ASSIGN(
         auto encoded_null_value,
         checked_cast<const 
DictionaryScalar&>(scalar_null_value).GetEncodedValue());
     ASSERT_OK(encoded_null_value->ValidateFull());
-    ASSERT_TRUE(encoded_null_value->Equals(MakeNullScalar(utf8())));
+    ASSERT_TRUE(encoded_null_value->Equals(*MakeNullScalar(utf8())));
 
     ASSERT_OK_AND_ASSIGN(
         auto encoded_alpha,
         checked_cast<const DictionaryScalar&>(scalar_alpha).GetEncodedValue());
     ASSERT_OK(encoded_alpha->ValidateFull());
-    ASSERT_TRUE(encoded_alpha->Equals(MakeScalar("alpha")));
+    ASSERT_TRUE(encoded_alpha->Equals(*MakeScalar("alpha")));
 
     ASSERT_OK_AND_ASSIGN(
         auto encoded_gamma,
         checked_cast<const DictionaryScalar&>(scalar_gamma).GetEncodedValue());
     ASSERT_OK(encoded_gamma->ValidateFull());
-    ASSERT_TRUE(encoded_gamma->Equals(MakeScalar("gamma")));
+    ASSERT_TRUE(encoded_gamma->Equals(*MakeScalar("gamma")));
 
     // test Array.GetScalar
     DictionaryArray arr(ty, ArrayFromJSON(index_ty, "[2, 0, 1, null]"), dict);
@@ -1306,7 +1306,7 @@ TEST(TestDictionaryScalar, Basics) {
 
     ASSERT_TRUE(first->Equals(scalar_gamma));
     ASSERT_TRUE(second->Equals(scalar_alpha));
-    ASSERT_TRUE(last->Equals(scalar_null));
+    ASSERT_TRUE(last->Equals(*scalar_null));
 
     auto first_dict_scalar = checked_cast<const DictionaryScalar&>(*first);
     ASSERT_TRUE(first_dict_scalar.value.dictionary->Equals(arr.dictionary()));
@@ -1397,7 +1397,7 @@ TEST(TestDictionaryScalar, Cast) {
       AssertScalarsEqual(*encoded_alpha, *roundtripped_alpha);
 
       // dictionaries differ, though encoded values are identical
-      ASSERT_FALSE(alpha_dict.Equals(cast_alpha));
+      ASSERT_FALSE(alpha_dict.Equals(*cast_alpha));
     }
   }
 }
@@ -1415,7 +1415,7 @@ void CheckGetValidUnionScalar(const Array& arr, int64_t 
index, const Scalar& exp
 
 void CheckGetNullUnionScalar(const Array& arr, int64_t index) {
   ASSERT_OK_AND_ASSIGN(auto scalar, arr.GetScalar(index));
-  ASSERT_TRUE(scalar->Equals(MakeNullScalar(arr.type())));
+  ASSERT_TRUE(scalar->Equals(*MakeNullScalar(arr.type())));
 
   ASSERT_FALSE(scalar->is_valid);
   ASSERT_FALSE(checked_cast<const 
UnionScalar&>(*scalar).child_value()->is_valid);
@@ -1535,17 +1535,17 @@ class TestUnionScalar : public ::testing::Test {
 
   void TestEquals() {
     // Differing values
-    ASSERT_FALSE(union_alpha_->Equals(union_beta_));
-    ASSERT_FALSE(union_two_->Equals(union_three_));
+    ASSERT_FALSE(union_alpha_->Equals(*union_beta_));
+    ASSERT_FALSE(union_two_->Equals(*union_three_));
     // Differing validities
-    ASSERT_FALSE(union_alpha_->Equals(union_string_null_));
+    ASSERT_FALSE(union_alpha_->Equals(*union_string_null_));
     // Differing types
-    ASSERT_FALSE(union_alpha_->Equals(union_two_));
-    ASSERT_FALSE(union_alpha_->Equals(union_other_two_));
+    ASSERT_FALSE(union_alpha_->Equals(*union_two_));
+    ASSERT_FALSE(union_alpha_->Equals(*union_other_two_));
     // Type codes don't count when comparing union scalars: the underlying 
values
     // are identical even though their provenance is different.
-    ASSERT_TRUE(union_two_->Equals(union_other_two_));
-    ASSERT_TRUE(union_string_null_->Equals(union_number_null_));
+    ASSERT_TRUE(union_two_->Equals(*union_other_two_));
+    ASSERT_TRUE(union_string_null_->Equals(*union_number_null_));
   }
 
   void TestMakeNullScalar() {
diff --git a/cpp/src/arrow/testing/json_integration.cc 
b/cpp/src/arrow/testing/json_integration.cc
index 2af094a781..a6bed8ca19 100644
--- a/cpp/src/arrow/testing/json_integration.cc
+++ b/cpp/src/arrow/testing/json_integration.cc
@@ -146,7 +146,7 @@ class IntegrationJsonReader::Impl {
 
     RETURN_NOT_OK(json::ReadSchema(doc_, pool_, &dictionary_memo_, &schema_));
 
-    auto it = doc_.FindMember("batches");
+    auto it = std::as_const(doc_).FindMember("batches");
     RETURN_NOT_ARRAY("batches", it, doc_);
     record_batches_ = &it->value;
 
diff --git a/cpp/src/arrow/testing/matchers.h b/cpp/src/arrow/testing/matchers.h
index 34792525a7..b4625b3922 100644
--- a/cpp/src/arrow/testing/matchers.h
+++ b/cpp/src/arrow/testing/matchers.h
@@ -71,6 +71,8 @@ class AnyOfJSONMatcher {
   template <typename arg_type>
   operator testing::Matcher<arg_type>() const {  // NOLINT runtime/explicit
     struct Impl : testing::MatcherInterface<const arg_type&> {
+      static_assert(std::is_same<arg_type, std::shared_ptr<Scalar>>(),
+                    "AnyOfJSON only supported for std::shared_ptr<Scalar>");
       Impl(std::shared_ptr<DataType> type, std::string array_json)
           : type_(std::move(type)), array_json_(std::move(array_json)) {
         array = ArrayFromJSON(type_, array_json_);
@@ -98,7 +100,7 @@ class AnyOfJSONMatcher {
             return false;
           }
 
-          if (scalar->Equals(arg)) return true;
+          if (scalar->Equals(*arg)) return true;
         }
         *result_listener << "Argument scalar: '" << arg->ToString()
                          << "' matches no scalar from " << array->ToString();
diff --git a/cpp/src/arrow/util/compare.h b/cpp/src/arrow/util/compare.h
index 6477bf139f..0594b6002f 100644
--- a/cpp/src/arrow/util/compare.h
+++ b/cpp/src/arrow/util/compare.h
@@ -47,12 +47,12 @@ class EqualityComparable {
 
   struct PtrsEqual {
     bool operator()(const std::shared_ptr<T>& l, const std::shared_ptr<T>& r) 
const {
-      return l->Equals(r);
+      return l->Equals(*r);
     }
   };
 
-  bool operator==(const T& other) const { return cast().Equals(other); }
-  bool operator!=(const T& other) const { return !(cast() == other); }
+  friend bool operator==(T const& a, T const& b) { return a.Equals(b); }
+  friend bool operator!=(T const& a, T const& b) { return !(a == b); }
 
  private:
   const T& cast() const { return static_cast<const T&>(*this); }
diff --git a/r/src/scalar.cpp b/r/src/scalar.cpp
index 0fdf5bddbb..c78b5c1405 100644
--- a/r/src/scalar.cpp
+++ b/r/src/scalar.cpp
@@ -83,7 +83,7 @@ std::shared_ptr<arrow::DataType> Scalar__type(const 
std::shared_ptr<arrow::Scala
 // [[arrow::export]]
 bool Scalar__Equals(const std::shared_ptr<arrow::Scalar>& lhs,
                     const std::shared_ptr<arrow::Scalar>& rhs) {
-  return lhs->Equals(rhs);
+  return lhs->Equals(*rhs);
 }
 
 // [[arrow::export]]

Reply via email to