diff --git a/include/flatbuffers/array.h b/include/flatbuffers/array.h index f4bfbf054..68c245de8 100644 --- a/include/flatbuffers/array.h +++ b/include/flatbuffers/array.h @@ -31,13 +31,10 @@ template class Array { // Array can carry only POD data types (scalars or structs). typedef typename flatbuffers::bool_constant::value> scalar_tag; - typedef - typename flatbuffers::conditional::type - IndirectHelperType; public: typedef uint16_t size_type; - typedef typename IndirectHelper::return_type return_type; + typedef typename IndirectHelper::return_type return_type; typedef VectorConstIterator const_iterator; typedef VectorReverseIterator const_reverse_iterator; @@ -50,7 +47,7 @@ template class Array { return_type Get(uoffset_t i) const { FLATBUFFERS_ASSERT(i < size()); - return IndirectHelper::Read(Data(), i); + return IndirectHelper::Read(Data(), i); } return_type operator[](uoffset_t i) const { return Get(i); } diff --git a/include/flatbuffers/buffer.h b/include/flatbuffers/buffer.h index 94d4f7903..00c07c736 100644 --- a/include/flatbuffers/buffer.h +++ b/include/flatbuffers/buffer.h @@ -20,6 +20,7 @@ #include #include "flatbuffers/base.h" +#include "flatbuffers/stl_emulation.h" namespace flatbuffers { @@ -36,6 +37,10 @@ template struct Offset { bool IsNull() const { return !o; } }; +template struct is_specialisation_of_Offset : false_type {}; +template +struct is_specialisation_of_Offset> : true_type {}; + // Wrapper for uoffset64_t Offsets. template struct Offset64 { // The type of offset to use. @@ -48,6 +53,10 @@ template struct Offset64 { bool IsNull() const { return !o; } }; +template struct is_specialisation_of_Offset64 : false_type {}; +template +struct is_specialisation_of_Offset64> : true_type {}; + // Litmus check for ensuring the Offsets are the expected size. static_assert(sizeof(Offset<>) == 4, "Offset has wrong size"); static_assert(sizeof(Offset64<>) == 8, "Offset64 has wrong size"); @@ -90,7 +99,7 @@ static inline bool StringLessThan(const char *a_data, uoffset_t a_size, // return type like this. // The typedef is for the convenience of callers of this function // (avoiding the need for a trailing return decltype) -template struct IndirectHelper { +template struct IndirectHelper { typedef T return_type; typedef T mutable_return_type; static const size_t element_stride = sizeof(T); @@ -135,10 +144,20 @@ struct IndirectHelper> { }; // For vector of structs. -template struct IndirectHelper { - typedef const T *return_type; - typedef T *mutable_return_type; - static const size_t element_stride = sizeof(T); +template +struct IndirectHelper< + T, typename std::enable_if< + !std::is_scalar::type>::value && + !is_specialisation_of_Offset::value && + !is_specialisation_of_Offset64::value>::type> { + private: + typedef typename std::remove_pointer::type>::type + pointee_type; + + public: + typedef const pointee_type *return_type; + typedef pointee_type *mutable_return_type; + static const size_t element_stride = sizeof(pointee_type); static return_type Read(const uint8_t *const p, const size_t i) { // Structs are stored inline, relative to the first struct pointer. diff --git a/tests/test.cpp b/tests/test.cpp index af8cd6347..a374da575 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -834,6 +834,24 @@ void FixedLengthArrayConstructorTest() { TEST_EQ(arr_struct.e(), 10); TEST_EQ(arr_struct.f()->Get(0), -2); TEST_EQ(arr_struct.f()->Get(1), -1); + + // Test for each loop over NestedStruct entries + for (auto i : *arr_struct.d()) { + for (auto a : *i->a()) { + TEST_EQ(a, 1); + break; // one iteration is enough, just testing compilation + } + TEST_EQ(i->b(), MyGame::Example::TestEnum::B); + for (auto c : *i->c()) { + TEST_EQ(c, MyGame::Example::TestEnum::A); + break; // one iteration is enough, just testing compilation + } + for (auto d : *i->d()) { + TEST_EQ(d, -2); + break; // one iteration is enough, just testing compilation + } + break; // one iteration is enough, just testing compilation + } } #else void FixedLengthArrayConstructorTest() {}