1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // This header defines the RepeatedFieldRef class template used to access
32 // repeated fields with protobuf reflection API.
33 #ifndef GOOGLE_PROTOBUF_REFLECTION_H__
34 #define GOOGLE_PROTOBUF_REFLECTION_H__
35
36 #include <memory>
37
38 #include <google/protobuf/message.h>
39 #include <google/protobuf/generated_enum_util.h>
40
41 #ifdef SWIG
42 #error "You cannot SWIG proto headers"
43 #endif
44
45 #include <google/protobuf/port_def.inc>
46
47 namespace google {
48 namespace protobuf {
49 namespace internal {
50 template <typename T, typename Enable = void>
51 struct RefTypeTraits;
52 } // namespace internal
53
54 template <typename T>
GetRepeatedFieldRef(const Message & message,const FieldDescriptor * field)55 RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef(
56 const Message& message, const FieldDescriptor* field) const {
57 return RepeatedFieldRef<T>(message, field);
58 }
59
60 template <typename T>
GetMutableRepeatedFieldRef(Message * message,const FieldDescriptor * field)61 MutableRepeatedFieldRef<T> Reflection::GetMutableRepeatedFieldRef(
62 Message* message, const FieldDescriptor* field) const {
63 return MutableRepeatedFieldRef<T>(message, field);
64 }
65
66 // RepeatedFieldRef definition for non-message types.
67 template <typename T>
68 class RepeatedFieldRef<
69 T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> {
70 typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
71 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
72
73 public:
empty()74 bool empty() const { return accessor_->IsEmpty(data_); }
size()75 int size() const { return accessor_->Size(data_); }
Get(int index)76 T Get(int index) const { return accessor_->template Get<T>(data_, index); }
77
78 typedef IteratorType iterator;
79 typedef IteratorType const_iterator;
80 typedef T value_type;
81 typedef T& reference;
82 typedef const T& const_reference;
83 typedef int size_type;
84 typedef ptrdiff_t difference_type;
85
begin()86 iterator begin() const { return iterator(data_, accessor_, true); }
end()87 iterator end() const { return iterator(data_, accessor_, false); }
88
89 private:
90 friend class Reflection;
RepeatedFieldRef(const Message & message,const FieldDescriptor * field)91 RepeatedFieldRef(const Message& message, const FieldDescriptor* field) {
92 const Reflection* reflection = message.GetReflection();
93 data_ = reflection->RepeatedFieldData(const_cast<Message*>(&message), field,
94 internal::RefTypeTraits<T>::cpp_type,
95 NULL);
96 accessor_ = reflection->RepeatedFieldAccessor(field);
97 }
98
99 const void* data_;
100 const AccessorType* accessor_;
101 };
102
103 // MutableRepeatedFieldRef definition for non-message types.
104 template <typename T>
105 class MutableRepeatedFieldRef<
106 T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> {
107 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
108
109 public:
empty()110 bool empty() const { return accessor_->IsEmpty(data_); }
size()111 int size() const { return accessor_->Size(data_); }
Get(int index)112 T Get(int index) const { return accessor_->template Get<T>(data_, index); }
113
Set(int index,const T & value)114 void Set(int index, const T& value) const {
115 accessor_->template Set<T>(data_, index, value);
116 }
Add(const T & value)117 void Add(const T& value) const { accessor_->template Add<T>(data_, value); }
RemoveLast()118 void RemoveLast() const { accessor_->RemoveLast(data_); }
SwapElements(int index1,int index2)119 void SwapElements(int index1, int index2) const {
120 accessor_->SwapElements(data_, index1, index2);
121 }
Clear()122 void Clear() const { accessor_->Clear(data_); }
123
Swap(const MutableRepeatedFieldRef & other)124 void Swap(const MutableRepeatedFieldRef& other) const {
125 accessor_->Swap(data_, other.accessor_, other.data_);
126 }
127
128 template <typename Container>
MergeFrom(const Container & container)129 void MergeFrom(const Container& container) const {
130 typedef typename Container::const_iterator Iterator;
131 for (Iterator it = container.begin(); it != container.end(); ++it) {
132 Add(*it);
133 }
134 }
135 template <typename Container>
CopyFrom(const Container & container)136 void CopyFrom(const Container& container) const {
137 Clear();
138 MergeFrom(container);
139 }
140
141 private:
142 friend class Reflection;
MutableRepeatedFieldRef(Message * message,const FieldDescriptor * field)143 MutableRepeatedFieldRef(Message* message, const FieldDescriptor* field) {
144 const Reflection* reflection = message->GetReflection();
145 data_ = reflection->RepeatedFieldData(
146 message, field, internal::RefTypeTraits<T>::cpp_type, NULL);
147 accessor_ = reflection->RepeatedFieldAccessor(field);
148 }
149
150 void* data_;
151 const AccessorType* accessor_;
152 };
153
154 // RepeatedFieldRef definition for message types.
155 template <typename T>
156 class RepeatedFieldRef<
157 T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
158 typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
159 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
160
161 public:
empty()162 bool empty() const { return accessor_->IsEmpty(data_); }
size()163 int size() const { return accessor_->Size(data_); }
164 // This method returns a reference to the underlying message object if it
165 // exists. If a message object doesn't exist (e.g., data stored in serialized
166 // form), scratch_space will be filled with the data and a reference to it
167 // will be returned.
168 //
169 // Example:
170 // RepeatedFieldRef<Message> h = ...
171 // unique_ptr<Message> scratch_space(h.NewMessage());
172 // const Message& item = h.Get(index, scratch_space.get());
Get(int index,T * scratch_space)173 const T& Get(int index, T* scratch_space) const {
174 return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
175 }
176 // Create a new message of the same type as the messages stored in this
177 // repeated field. Caller takes ownership of the returned object.
NewMessage()178 T* NewMessage() const { return static_cast<T*>(default_instance_->New()); }
179
180 typedef IteratorType iterator;
181 typedef IteratorType const_iterator;
182 typedef T value_type;
183 typedef T& reference;
184 typedef const T& const_reference;
185 typedef int size_type;
186 typedef ptrdiff_t difference_type;
187
begin()188 iterator begin() const {
189 return iterator(data_, accessor_, true, NewMessage());
190 }
end()191 iterator end() const {
192 // The end iterator must not be dereferenced, no need for scratch space.
193 return iterator(data_, accessor_, false, nullptr);
194 }
195
196 private:
197 friend class Reflection;
RepeatedFieldRef(const Message & message,const FieldDescriptor * field)198 RepeatedFieldRef(const Message& message, const FieldDescriptor* field) {
199 const Reflection* reflection = message.GetReflection();
200 data_ = reflection->RepeatedFieldData(
201 const_cast<Message*>(&message), field,
202 internal::RefTypeTraits<T>::cpp_type,
203 internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
204 accessor_ = reflection->RepeatedFieldAccessor(field);
205 default_instance_ =
206 reflection->GetMessageFactory()->GetPrototype(field->message_type());
207 }
208
209 const void* data_;
210 const AccessorType* accessor_;
211 const Message* default_instance_;
212 };
213
214 // MutableRepeatedFieldRef definition for message types.
215 template <typename T>
216 class MutableRepeatedFieldRef<
217 T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
218 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
219
220 public:
empty()221 bool empty() const { return accessor_->IsEmpty(data_); }
size()222 int size() const { return accessor_->Size(data_); }
223 // See comments for RepeatedFieldRef<Message>::Get()
Get(int index,T * scratch_space)224 const T& Get(int index, T* scratch_space) const {
225 return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
226 }
227 // Create a new message of the same type as the messages stored in this
228 // repeated field. Caller takes ownership of the returned object.
NewMessage()229 T* NewMessage() const { return static_cast<T*>(default_instance_->New()); }
230
Set(int index,const T & value)231 void Set(int index, const T& value) const {
232 accessor_->Set(data_, index, &value);
233 }
Add(const T & value)234 void Add(const T& value) const { accessor_->Add(data_, &value); }
RemoveLast()235 void RemoveLast() const { accessor_->RemoveLast(data_); }
SwapElements(int index1,int index2)236 void SwapElements(int index1, int index2) const {
237 accessor_->SwapElements(data_, index1, index2);
238 }
Clear()239 void Clear() const { accessor_->Clear(data_); }
240
Swap(const MutableRepeatedFieldRef & other)241 void Swap(const MutableRepeatedFieldRef& other) const {
242 accessor_->Swap(data_, other.accessor_, other.data_);
243 }
244
245 template <typename Container>
MergeFrom(const Container & container)246 void MergeFrom(const Container& container) const {
247 typedef typename Container::const_iterator Iterator;
248 for (Iterator it = container.begin(); it != container.end(); ++it) {
249 Add(*it);
250 }
251 }
252 template <typename Container>
CopyFrom(const Container & container)253 void CopyFrom(const Container& container) const {
254 Clear();
255 MergeFrom(container);
256 }
257
258 private:
259 friend class Reflection;
MutableRepeatedFieldRef(Message * message,const FieldDescriptor * field)260 MutableRepeatedFieldRef(Message* message, const FieldDescriptor* field) {
261 const Reflection* reflection = message->GetReflection();
262 data_ = reflection->RepeatedFieldData(
263 message, field, internal::RefTypeTraits<T>::cpp_type,
264 internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
265 accessor_ = reflection->RepeatedFieldAccessor(field);
266 default_instance_ =
267 reflection->GetMessageFactory()->GetPrototype(field->message_type());
268 }
269
270 void* data_;
271 const AccessorType* accessor_;
272 const Message* default_instance_;
273 };
274
275 namespace internal {
276 // Interfaces used to implement reflection RepeatedFieldRef API.
277 // Reflection::GetRepeatedAccessor() should return a pointer to an singleton
278 // object that implements the below interface.
279 //
280 // This interface passes/returns values using void pointers. The actual type
281 // of the value depends on the field's cpp_type. Following is a mapping from
282 // cpp_type to the type that should be used in this interface:
283 //
284 // field->cpp_type() T Actual type of void*
285 // CPPTYPE_INT32 int32 int32
286 // CPPTYPE_UINT32 uint32 uint32
287 // CPPTYPE_INT64 int64 int64
288 // CPPTYPE_UINT64 uint64 uint64
289 // CPPTYPE_DOUBLE double double
290 // CPPTYPE_FLOAT float float
291 // CPPTYPE_BOOL bool bool
292 // CPPTYPE_ENUM generated enum type int32
293 // CPPTYPE_STRING string std::string
294 // CPPTYPE_MESSAGE generated message type google::protobuf::Message
295 // or google::protobuf::Message
296 //
297 // Note that for enums we use int32 in the interface.
298 //
299 // You can map from T to the actual type using RefTypeTraits:
300 // typedef RefTypeTraits<T>::AccessorValueType ActualType;
301 class PROTOBUF_EXPORT RepeatedFieldAccessor {
302 public:
303 // Typedefs for clarity.
304 typedef void Field;
305 typedef void Value;
306 typedef void Iterator;
307
308 virtual bool IsEmpty(const Field* data) const = 0;
309 virtual int Size(const Field* data) const = 0;
310 // Depends on the underlying representation of the repeated field, this
311 // method can return a pointer to the underlying object if such an object
312 // exists, or fill the data into scratch_space and return scratch_space.
313 // Callers of this method must ensure scratch_space is a valid pointer
314 // to a mutable object of the correct type.
315 virtual const Value* Get(const Field* data, int index,
316 Value* scratch_space) const = 0;
317
318 virtual void Clear(Field* data) const = 0;
319 virtual void Set(Field* data, int index, const Value* value) const = 0;
320 virtual void Add(Field* data, const Value* value) const = 0;
321 virtual void RemoveLast(Field* data) const = 0;
322 virtual void SwapElements(Field* data, int index1, int index2) const = 0;
323 virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
324 Field* other_data) const = 0;
325
326 // Create an iterator that points at the beginning of the repeated field.
327 virtual Iterator* BeginIterator(const Field* data) const = 0;
328 // Create an iterator that points at the end of the repeated field.
329 virtual Iterator* EndIterator(const Field* data) const = 0;
330 // Make a copy of an iterator and return the new copy.
331 virtual Iterator* CopyIterator(const Field* data,
332 const Iterator* iterator) const = 0;
333 // Move an iterator to point to the next element.
334 virtual Iterator* AdvanceIterator(const Field* data,
335 Iterator* iterator) const = 0;
336 // Compare whether two iterators point to the same element.
337 virtual bool EqualsIterator(const Field* data, const Iterator* a,
338 const Iterator* b) const = 0;
339 // Delete an iterator created by BeginIterator(), EndIterator() and
340 // CopyIterator().
341 virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
342 // Like Get() but for iterators.
343 virtual const Value* GetIteratorValue(const Field* data,
344 const Iterator* iterator,
345 Value* scratch_space) const = 0;
346
347 // Templated methods that make using this interface easier for non-message
348 // types.
349 template <typename T>
Get(const Field * data,int index)350 T Get(const Field* data, int index) const {
351 typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
352 ActualType scratch_space;
353 return static_cast<T>(*reinterpret_cast<const ActualType*>(
354 Get(data, index, static_cast<Value*>(&scratch_space))));
355 }
356
357 template <typename T, typename ValueType>
Set(Field * data,int index,const ValueType & value)358 void Set(Field* data, int index, const ValueType& value) const {
359 typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
360 // In this RepeatedFieldAccessor interface we pass/return data using
361 // raw pointers. Type of the data these raw pointers point to should
362 // be ActualType. Here we have a ValueType object and want a ActualType
363 // pointer. We can't cast a ValueType pointer to an ActualType pointer
364 // directly because their type might be different (for enums ValueType
365 // may be a generated enum type while ActualType is int32). To be safe
366 // we make a copy to get a temporary ActualType object and use it.
367 ActualType tmp = static_cast<ActualType>(value);
368 Set(data, index, static_cast<const Value*>(&tmp));
369 }
370
371 template <typename T, typename ValueType>
Add(Field * data,const ValueType & value)372 void Add(Field* data, const ValueType& value) const {
373 typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
374 // In this RepeatedFieldAccessor interface we pass/return data using
375 // raw pointers. Type of the data these raw pointers point to should
376 // be ActualType. Here we have a ValueType object and want a ActualType
377 // pointer. We can't cast a ValueType pointer to an ActualType pointer
378 // directly because their type might be different (for enums ValueType
379 // may be a generated enum type while ActualType is int32). To be safe
380 // we make a copy to get a temporary ActualType object and use it.
381 ActualType tmp = static_cast<ActualType>(value);
382 Add(data, static_cast<const Value*>(&tmp));
383 }
384
385 protected:
386 // We want the destructor to be completely trivial as to allow it to be
387 // a function local static. Hence we make it non-virtual and protected,
388 // this class only live as part of a global singleton and should not be
389 // deleted.
390 ~RepeatedFieldAccessor() = default;
391 };
392
393 // Implement (Mutable)RepeatedFieldRef::iterator
394 template <typename T>
395 class RepeatedFieldRefIterator
396 : public std::iterator<std::forward_iterator_tag, T> {
397 typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
398 typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
399 typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
400
401 public:
402 // Constructor for non-message fields.
RepeatedFieldRefIterator(const void * data,const RepeatedFieldAccessor * accessor,bool begin)403 RepeatedFieldRefIterator(const void* data,
404 const RepeatedFieldAccessor* accessor, bool begin)
405 : data_(data),
406 accessor_(accessor),
407 iterator_(begin ? accessor->BeginIterator(data)
408 : accessor->EndIterator(data)),
409 // The end iterator must not be dereferenced, no need for scratch space.
410 scratch_space_(begin ? new AccessorValueType : nullptr) {}
411 // Constructor for message fields.
RepeatedFieldRefIterator(const void * data,const RepeatedFieldAccessor * accessor,bool begin,AccessorValueType * scratch_space)412 RepeatedFieldRefIterator(const void* data,
413 const RepeatedFieldAccessor* accessor, bool begin,
414 AccessorValueType* scratch_space)
415 : data_(data),
416 accessor_(accessor),
417 iterator_(begin ? accessor->BeginIterator(data)
418 : accessor->EndIterator(data)),
419 scratch_space_(scratch_space) {}
~RepeatedFieldRefIterator()420 ~RepeatedFieldRefIterator() { accessor_->DeleteIterator(data_, iterator_); }
421 RepeatedFieldRefIterator operator++(int) {
422 RepeatedFieldRefIterator tmp(*this);
423 iterator_ = accessor_->AdvanceIterator(data_, iterator_);
424 return tmp;
425 }
426 RepeatedFieldRefIterator& operator++() {
427 iterator_ = accessor_->AdvanceIterator(data_, iterator_);
428 return *this;
429 }
430 IteratorValueType operator*() const {
431 return static_cast<IteratorValueType>(
432 *static_cast<const AccessorValueType*>(accessor_->GetIteratorValue(
433 data_, iterator_, scratch_space_.get())));
434 }
435 IteratorPointerType operator->() const {
436 return static_cast<IteratorPointerType>(
437 accessor_->GetIteratorValue(data_, iterator_, scratch_space_.get()));
438 }
439 bool operator!=(const RepeatedFieldRefIterator& other) const {
440 assert(data_ == other.data_);
441 assert(accessor_ == other.accessor_);
442 return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
443 }
444 bool operator==(const RepeatedFieldRefIterator& other) const {
445 return !this->operator!=(other);
446 }
447
RepeatedFieldRefIterator(const RepeatedFieldRefIterator & other)448 RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
449 : data_(other.data_),
450 accessor_(other.accessor_),
451 iterator_(accessor_->CopyIterator(data_, other.iterator_)) {}
452 RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
453 if (this != &other) {
454 accessor_->DeleteIterator(data_, iterator_);
455 data_ = other.data_;
456 accessor_ = other.accessor_;
457 iterator_ = accessor_->CopyIterator(data_, other.iterator_);
458 }
459 return *this;
460 }
461
462 protected:
463 const void* data_;
464 const RepeatedFieldAccessor* accessor_;
465 void* iterator_;
466 std::unique_ptr<AccessorValueType> scratch_space_;
467 };
468
469 // TypeTraits that maps the type parameter T of RepeatedFieldRef or
470 // MutableRepeatedFieldRef to corresponding iterator type,
471 // RepeatedFieldAccessor type, etc.
472 template <typename T>
473 struct PrimitiveTraits {
474 static const bool is_primitive = false;
475 };
476 #define DEFINE_PRIMITIVE(TYPE, type) \
477 template <> \
478 struct PrimitiveTraits<type> { \
479 static const bool is_primitive = true; \
480 static const FieldDescriptor::CppType cpp_type = \
481 FieldDescriptor::CPPTYPE_##TYPE; \
482 };
483 DEFINE_PRIMITIVE(INT32, int32)
484 DEFINE_PRIMITIVE(UINT32, uint32)
485 DEFINE_PRIMITIVE(INT64, int64)
486 DEFINE_PRIMITIVE(UINT64, uint64)
487 DEFINE_PRIMITIVE(FLOAT, float)
488 DEFINE_PRIMITIVE(DOUBLE, double)
489 DEFINE_PRIMITIVE(BOOL, bool)
490 #undef DEFINE_PRIMITIVE
491
492 template <typename T>
493 struct RefTypeTraits<
494 T, typename std::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
495 typedef RepeatedFieldRefIterator<T> iterator;
496 typedef RepeatedFieldAccessor AccessorType;
497 typedef T AccessorValueType;
498 typedef T IteratorValueType;
499 typedef T* IteratorPointerType;
500 static const FieldDescriptor::CppType cpp_type = PrimitiveTraits<T>::cpp_type;
501 static const Descriptor* GetMessageFieldDescriptor() { return NULL; }
502 };
503
504 template <typename T>
505 struct RefTypeTraits<
506 T, typename std::enable_if<is_proto_enum<T>::value>::type> {
507 typedef RepeatedFieldRefIterator<T> iterator;
508 typedef RepeatedFieldAccessor AccessorType;
509 // We use int32 for repeated enums in RepeatedFieldAccessor.
510 typedef int32 AccessorValueType;
511 typedef T IteratorValueType;
512 typedef int32* IteratorPointerType;
513 static const FieldDescriptor::CppType cpp_type =
514 FieldDescriptor::CPPTYPE_ENUM;
515 static const Descriptor* GetMessageFieldDescriptor() { return NULL; }
516 };
517
518 template <typename T>
519 struct RefTypeTraits<
520 T, typename std::enable_if<std::is_same<std::string, T>::value>::type> {
521 typedef RepeatedFieldRefIterator<T> iterator;
522 typedef RepeatedFieldAccessor AccessorType;
523 typedef std::string AccessorValueType;
524 typedef const std::string IteratorValueType;
525 typedef const std::string* IteratorPointerType;
526 static const FieldDescriptor::CppType cpp_type =
527 FieldDescriptor::CPPTYPE_STRING;
528 static const Descriptor* GetMessageFieldDescriptor() { return NULL; }
529 };
530
531 template <typename T>
532 struct MessageDescriptorGetter {
533 static const Descriptor* get() {
534 return T::default_instance().GetDescriptor();
535 }
536 };
537 template <>
538 struct MessageDescriptorGetter<Message> {
539 static const Descriptor* get() { return NULL; }
540 };
541
542 template <typename T>
543 struct RefTypeTraits<
544 T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
545 typedef RepeatedFieldRefIterator<T> iterator;
546 typedef RepeatedFieldAccessor AccessorType;
547 typedef Message AccessorValueType;
548 typedef const T& IteratorValueType;
549 typedef const T* IteratorPointerType;
550 static const FieldDescriptor::CppType cpp_type =
551 FieldDescriptor::CPPTYPE_MESSAGE;
552 static const Descriptor* GetMessageFieldDescriptor() {
553 return MessageDescriptorGetter<T>::get();
554 }
555 };
556 } // namespace internal
557 } // namespace protobuf
558 } // namespace google
559
560 #include <google/protobuf/port_undef.inc>
561
562 #endif // GOOGLE_PROTOBUF_REFLECTION_H__
563