| 
					
				 | 
			
			
				@@ -23,6 +23,8 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "gmock/gmock.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "gtest/gtest.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "absl/base/attributes.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "absl/memory/memory.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "absl/strings/str_cat.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 namespace { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -38,8 +40,9 @@ namespace { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #pragma warning( disable : 4101 )  // unreferenced local variable 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif  // _MSC_VER 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-using testing::StaticAssertTypeEq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-using testing::ElementsAre; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using ::testing::ElementsAre; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using ::testing::Pointee; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using ::testing::StaticAssertTypeEq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 TEST(IntegerSequenceTest, ValueType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   StaticAssertTypeEq<int, absl::integer_sequence<int>::value_type>(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -159,5 +162,176 @@ TEST(IndexSequenceForTest, Example) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               ElementsAre("12", "abc", "3.14")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int Function(int a, int b) { return a - b; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int Sink(std::unique_ptr<int> p) { return *p; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void NoOp() {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct ConstFunctor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int operator()(int a, int b) const { return a - b; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct MutableFunctor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int operator()(int a, int b) { return a - b; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct EphemeralFunctor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EphemeralFunctor() {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EphemeralFunctor(const EphemeralFunctor&) {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EphemeralFunctor(EphemeralFunctor&&) {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int operator()(int a, int b) && { return a - b; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct OverloadedFunctor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  OverloadedFunctor() {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  OverloadedFunctor(const OverloadedFunctor&) {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  OverloadedFunctor(OverloadedFunctor&&) {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  template <typename... Args> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  std::string operator()(const Args&... args) & { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return absl::StrCat("&", args...); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  template <typename... Args> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  std::string operator()(const Args&... args) const& { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return absl::StrCat("const&", args...); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  template <typename... Args> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  std::string operator()(const Args&... args) && { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return absl::StrCat("&&", args...); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct Class { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int Method(int a, int b) { return a - b; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int ConstMethod(int a, int b) const { return a - b; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int member; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct FlipFlop { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int ConstMethod() const { return member; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  FlipFlop operator*() const { return {-member}; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int member; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, Function) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(Function, std::make_tuple(3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(&Function, std::make_tuple(3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, NonCopyableArgument) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(42, absl::apply(Sink, std::make_tuple(absl::make_unique<int>(42)))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, NonCopyableResult) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_THAT(absl::apply(Factory, std::make_tuple(42)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              ::testing::Pointee(42)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, VoidResult) { absl::apply(NoOp, std::tuple<>()); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, ConstFunctor) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(ConstFunctor(), std::make_tuple(3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, MutableFunctor) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  MutableFunctor f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(f, std::make_tuple(3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(MutableFunctor(), std::make_tuple(3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, EphemeralFunctor) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EphemeralFunctor f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(std::move(f), std::make_tuple(3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(EphemeralFunctor(), std::make_tuple(3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, OverloadedFunctor) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  OverloadedFunctor f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const OverloadedFunctor& cf = f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ("&", absl::apply(f, std::tuple<>{})); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ("& 42", absl::apply(f, std::make_tuple(" 42"))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ("const&", absl::apply(cf, std::tuple<>{})); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ("const& 42", absl::apply(cf, std::make_tuple(" 42"))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ("&&", absl::apply(std::move(f), std::tuple<>{})); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  OverloadedFunctor f2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ("&& 42", absl::apply(std::move(f2), std::make_tuple(" 42"))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, ReferenceWrapper) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ConstFunctor cf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  MutableFunctor mf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(std::cref(cf), std::make_tuple(3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(std::ref(cf), std::make_tuple(3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(std::ref(mf), std::make_tuple(3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, MemberFunction) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  std::unique_ptr<Class> p(new Class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  std::unique_ptr<const Class> cp(new Class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      1, absl::apply(&Class::Method, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                     std::tuple<std::unique_ptr<Class>&, int, int>(p, 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(&Class::Method, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           std::tuple<Class*, int, int>(p.get(), 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      1, absl::apply(&Class::Method, std::tuple<Class&, int, int>(*p, 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      1, absl::apply(&Class::ConstMethod, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                     std::tuple<std::unique_ptr<Class>&, int, int>(p, 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(&Class::ConstMethod, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           std::tuple<Class*, int, int>(p.get(), 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(&Class::ConstMethod, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           std::tuple<Class&, int, int>(*p, 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(&Class::ConstMethod, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           std::tuple<std::unique_ptr<const Class>&, int, int>( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               cp, 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(&Class::ConstMethod, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           std::tuple<const Class*, int, int>(cp.get(), 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(&Class::ConstMethod, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           std::tuple<const Class&, int, int>(*cp, 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(&Class::Method, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           std::make_tuple(absl::make_unique<Class>(), 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(1, absl::apply(&Class::ConstMethod, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           std::make_tuple(absl::make_unique<Class>(), 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      1, absl::apply(&Class::ConstMethod, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                     std::make_tuple(absl::make_unique<const Class>(), 3, 2))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, DataMember) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  std::unique_ptr<Class> p(new Class{42}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  std::unique_ptr<const Class> cp(new Class{42}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      42, absl::apply(&Class::member, std::tuple<std::unique_ptr<Class>&>(p))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<Class&>(*p))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<Class*>(p.get()))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  absl::apply(&Class::member, std::tuple<std::unique_ptr<Class>&>(p)) = 42; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  absl::apply(&Class::member, std::tuple<Class*>(p.get())) = 42; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  absl::apply(&Class::member, std::tuple<Class&>(*p)) = 42; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(42, absl::apply(&Class::member, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            std::tuple<std::unique_ptr<const Class>&>(cp))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<const Class&>(*cp))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(42, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            absl::apply(&Class::member, std::tuple<const Class*>(cp.get()))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TEST(ApplyTest, FlipFlop) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  FlipFlop obj = {42}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // This call could resolve to (obj.*&FlipFlop::ConstMethod)() or 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(42, absl::apply(&FlipFlop::ConstMethod, std::make_tuple(obj))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  EXPECT_EQ(42, absl::apply(&FlipFlop::member, std::make_tuple(obj))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }  // namespace 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |