Browse Source

Fix issue 99.

Feng Xiao 11 years ago
parent
commit
6ae3bde73d

+ 6 - 7
src/google/protobuf/map.h

@@ -56,7 +56,7 @@ class MapField;
 template <typename Key, typename T>
 template <typename Key, typename T>
 class MapPair {
 class MapPair {
  public:
  public:
-  typedef Key first_type;
+  typedef const Key first_type;
   typedef T second_type;
   typedef T second_type;
 
 
   MapPair(const Key& other_first, const T& other_second)
   MapPair(const Key& other_first, const T& other_second)
@@ -67,14 +67,13 @@ class MapPair {
   MapPair(const MapPair& other)
   MapPair(const MapPair& other)
       : first(other.first), second(other.second) {}
       : first(other.first), second(other.second) {}
 
 
-  MapPair& operator=(const MapPair& other) {
-    first = other.first;
-    second = other.second;
-    return *this;
-  }
-
   ~MapPair() {}
   ~MapPair() {}
 
 
+  // Implicitly convertible to std::pair.
+  operator std::pair<const Key, T>() const {
+    return std::pair<const Key, T>(first, second);
+  }
+
   const Key first;
   const Key first;
   T second;
   T second;
 
 

+ 7 - 0
src/google/protobuf/map_field.h

@@ -213,6 +213,13 @@ class LIBPROTOBUF_EXPORT MapField : public MapFieldBase {
   mutable const EntryType* default_entry_;
   mutable const EntryType* default_entry_;
 };
 };
 
 
+// True if IsInitialized() is true for value field in all elements of t. T is
+// expected to be message.  It's useful to have this helper here to keep the
+// protobuf compiler from ever having to emit loops in IsInitialized() methods.
+// We want the C++ compiler to inline this or not as it sees fit.
+template <typename Key, typename T>
+bool AllAreInitialized(const Map<Key, T>& t);
+
 }  // namespace internal
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace protobuf
 
 

+ 9 - 0
src/google/protobuf/map_field_inl.h

@@ -262,6 +262,15 @@ void MapField<Key, T, KeyProto, ValueProto,
   }
   }
 }
 }
 
 
+template <typename Key, typename T>
+bool AllAreInitialized(const Map<Key, T>& t) {
+  for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
+       ++it) {
+    if (!it->second.IsInitialized()) return false;
+  }
+  return true;
+}
+
 }  // namespace internal
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace protobuf
 
 

+ 21 - 0
src/google/protobuf/map_test.cc

@@ -544,6 +544,13 @@ TEST_F(MapImplTest, EqualRange) {
   EXPECT_TRUE(const_map_.end() == const_range.second);
   EXPECT_TRUE(const_map_.end() == const_range.second);
 }
 }
 
 
+TEST_F(MapImplTest, ConvertToStdMap) {
+  map_[100] = 101;
+  std::map<int32, int32> std_map(map_.begin(), map_.end());
+  EXPECT_EQ(1, std_map.size());
+  EXPECT_EQ(101, std_map[100]);
+}
+
 // Map Field Reflection Test ========================================
 // Map Field Reflection Test ========================================
 
 
 static int Func(int i, int j) {
 static int Func(int i, int j) {
@@ -1740,6 +1747,20 @@ TEST(GeneratedMapFieldTest, MessageLiteMap) {
   EXPECT_EQ(1, to.map_field().at(1));
   EXPECT_EQ(1, to.map_field().at(1));
 }
 }
 
 
+TEST(GeneratedMapFieldTest, IsInitialized) {
+  unittest::TestRequiredMessageMap map_message;
+
+  // Add an uninitialized message.
+  (*map_message.mutable_map_field())[0];
+  EXPECT_FALSE(map_message.IsInitialized());
+
+  // Initialize uninitialized message
+  (*map_message.mutable_map_field())[0].set_a(0);
+  (*map_message.mutable_map_field())[0].set_b(0);
+  (*map_message.mutable_map_field())[0].set_c(0);
+  EXPECT_TRUE(map_message.IsInitialized());
+}
+
 // Generated Message Reflection Test ================================
 // Generated Message Reflection Test ================================
 
 
 TEST(GeneratedMapFieldReflectionTest, SpaceUsed) {
 TEST(GeneratedMapFieldReflectionTest, SpaceUsed) {

+ 5 - 0
src/google/protobuf/map_unittest.proto

@@ -75,3 +75,8 @@ enum MapEnum {
   MAP_ENUM_BAR = 1;
   MAP_ENUM_BAR = 1;
   MAP_ENUM_BAZ = 2;
   MAP_ENUM_BAZ = 2;
 }
 }
+
+// Test embeded message with required fields
+message TestRequiredMessageMap {
+  map<int32, TestRequired> map_field = 1;
+}