Skip to content

Commit

Permalink
Fixed compilation on VS2013 by providing workarounds for VS2013 buggy…
Browse files Browse the repository at this point in the history
… template template pack handling.
  • Loading branch information
constrictor committed Feb 24, 2025
1 parent a3bf13a commit 8989319
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 31 deletions.
107 changes: 89 additions & 18 deletions include/flatbuffers/flatbuffer_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -726,19 +726,21 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {

/// @brief Serialize an array into a FlatBuffer `vector`.
/// @tparam T The data type of the array elements.
/// @tparam OffsetT the type of offset to return
/// @tparam OffsetT the type of offset to return.
/// @tparam VectorT the type of vector to cast to.
/// @tparam SizeT the size type to use in the VectorT vector.
/// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `TOffset` into the serialized data indicating
/// where the vector is stored.
template<typename T, template<typename...> class OffsetT = Offset,
template<typename...> class VectorT = Vector>
OffsetT<VectorT<T>> CreateVector(const T *v, size_t len) {
template<typename T, template<typename...> class OffsetT,
template<typename...> class VectorT,
typename SizeT = typename VectorT<T>::size_type>
OffsetT<VectorT<T, SizeT>> CreateVector(const T *v, size_t len) {
// The type of the length field in the vector.
typedef typename VectorT<T>::size_type LenT;
typedef typename OffsetT<VectorT<T>>::offset_type offset_type;
typedef typename VectorT<T, SizeT>::size_type LenT;
typedef typename OffsetT<VectorT<T, SizeT>>::offset_type offset_type;
// If this assert hits, you're specifying a template argument that is
// causing the wrong overload to be selected, remove it.
AssertScalarT<T>();
Expand All @@ -758,7 +760,20 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {
#endif
// clang-format on
}
return OffsetT<VectorT<T>>(EndVector<LenT, offset_type>(len));
return OffsetT<VectorT<T, SizeT>>(EndVector<LenT, offset_type>(len));
}

/// @brief Serialize an array into a FlatBuffer `vector`.
/// @tparam T The data type of the array elements.
/// @tparam OffsetT the type of offset to return
/// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `TOffset` into the serialized data indicating
/// where the vector is stored.
template<typename T, template<typename...> class OffsetT = Offset>
OffsetT<Vector<T>> CreateVector(const T *v, size_t len) {
return CreateVector<T, OffsetT, Vector, typename Vector<T>::size_type>(v, len);
}

/// @brief Serialize an array like object into a FlatBuffer `vector`.
Expand Down Expand Up @@ -800,10 +815,22 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {
return CreateVector(data(v), v.size());
}

template<template<typename...> class VectorT = Vector64,
template<template<typename...> class VectorT,
typename SizeT,
int &...ExplicitArgumentBarrier, typename T>
Offset64<VectorT<T, SizeT>> CreateVector64(const std::vector<T> &v) {
return CreateVector<T, Offset64, VectorT, SizeT>(data(v), v.size());
}

template<template<typename...> class VectorT,
int &...ExplicitArgumentBarrier, typename T>
Offset64<VectorT<T>> CreateVector64(const std::vector<T> &v) {
return CreateVector<T, Offset64, VectorT>(data(v), v.size());
return CreateVector64<VectorT, typename VectorT<T>::size_type>(v);
}

template<typename T>
Offset64<Vector64<T>> CreateVector64(const std::vector<T> &v) {
return CreateVector64<Vector, typename Vector64<T>::size_type>(v);
}

// vector<bool> may be implemented using a bit-set, so we can't access it as
Expand Down Expand Up @@ -899,23 +926,38 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {

/// @brief Serialize an array of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements.
/// @tparam OffsetT the type of offset to return.
/// @tparam VectorT the type of vector to cast to.
/// @tparam SizeT the size type to use in the VectorT vector.
/// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, template<typename...> class OffsetT = Offset,
template<typename...> class VectorT = Vector>
OffsetT<VectorT<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
template<typename...> class VectorT, typename SizeT = typename VectorT<T>::size_type>
OffsetT<VectorT<const T *, SizeT>> CreateVectorOfStructs(const T *v, size_t len) {
// The type of the length field in the vector.
typedef typename VectorT<T>::size_type LenT;
typedef typename OffsetT<VectorT<const T *>>::offset_type offset_type;
typedef typename VectorT<T, SizeT>::size_type LenT;
typedef typename OffsetT<VectorT<const T *, SizeT>>::offset_type offset_type;

StartVector<OffsetT, LenT>(len, sizeof(T), AlignOf<T>());
if (len > 0) {
PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
}
return OffsetT<VectorT<const T *>>(EndVector<LenT, offset_type>(len));
return OffsetT<VectorT<const T *, SizeT>>(EndVector<LenT, offset_type>(len));
}

/// @brief Serialize an array of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements.
/// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T>
Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
return CreateVectorOfStructs<T, Offset, Vector, typename Vector<T>::size_type>(v, len);
}

/// @brief Serialize an array of structs into a FlatBuffer `vector`.
Expand Down Expand Up @@ -959,22 +1001,51 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {

/// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the `std::vector` struct elements.
/// @tparam OffsetT the type of offset to return.
/// @tparam VectorT the type of vector to cast to.
/// @tparam Alloc the allocator used by the parameter.
/// @tparam SizeT the size type to use in the VectorT vector.
/// @param[in] v A const reference to the `std::vector` of structs to
/// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, template<typename...> class OffsetT = Offset,
template<typename...> class VectorT = Vector,
typename Alloc = std::allocator<T>>
typename Alloc = std::allocator<T>, typename SizeT = typename VectorT<T>::size_type>
OffsetT<VectorT<const T *>> CreateVectorOfStructs(
const std::vector<T, Alloc> &v) {
return CreateVectorOfStructs<T, OffsetT, VectorT>(data(v), v.size());
}

template<template<typename...> class VectorT = Vector64, int &..., typename T>
/// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the `std::vector` struct elements.
/// @param[in] v A const reference to the `std::vector` of structs to
/// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T>
Offset<Vector<const T *>> CreateVectorOfStructs(
const std::vector<T, std::allocator<T>> &v) {
return CreateVectorOfStructs<T, Offset, Vector, typename Vector<T>::size_type>(data(v), v.size());
}

template<template<typename...> class VectorT, typename SizeT,
int &..., typename T>
Offset64<VectorT<const T *, SizeT>> CreateVectorOfStructs64(
const std::vector<T> &v) {
return CreateVectorOfStructs<T, Offset64, VectorT, SizeT>(data(v), v.size());
}

template<int &..., typename T>
Offset64<Vector64<const T *>> CreateVectorOfStructs64(
const std::vector<T> &v) {
return CreateVectorOfStructs<T, Offset64, Vector, typename Vector64<T>::size_type>(data(v), v.size());
}

template<template<typename...> class VectorT, int &..., typename T>
Offset64<VectorT<const T *>> CreateVectorOfStructs64(
const std::vector<T> &v) {
return CreateVectorOfStructs<T, Offset64, VectorT>(data(v), v.size());
return CreateVectorOfStructs64<VectorT, typename VectorT<T>::size_type>(data(v), v.size());
}

/// @brief Serialize an array of native structs into a FlatBuffer `vector`.
Expand Down Expand Up @@ -1087,7 +1158,7 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {
template<typename T>
Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
std::stable_sort(v, v + len, StructKeyComparator<T>());
return CreateVectorOfStructs(v, len);
return CreateVectorOfStructs<T, Offset, Vector, uoffset_t>(v, len);
}

/// @brief Serialize an array of native structs into a FlatBuffer `vector` in
Expand Down
8 changes: 4 additions & 4 deletions src/idl_gen_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3147,7 +3147,7 @@ class CppGenerator : public BaseGenerator {
code_ += "_fbb.CreateVectorOfStructs\\";
if (field->offset64) {
// This is normal 32-bit vector, with 64-bit addressing.
code_ += "64<::flatbuffers::Vector>\\";
code_ += "64<::flatbuffers::Vector, ::flatbuffers::uoffset_t>\\";
} else {
code_ += "<" + type + ">\\";
}
Expand All @@ -3166,7 +3166,7 @@ class CppGenerator : public BaseGenerator {
// If the field uses 64-bit addressing, create a 64-bit vector.
code_.SetValue("64OFFSET", field->offset64 ? "64" : "");
code_.SetValue("TYPE",
field->offset64 ? "::flatbuffers::Vector" : type);
field->offset64 ? "::flatbuffers::Vector, ::flatbuffers::uoffset_t" : type);

code_ += "_fbb.CreateVector{{64OFFSET}}<{{TYPE}}>\\";
}
Expand Down Expand Up @@ -3499,7 +3499,7 @@ class CppGenerator : public BaseGenerator {
code += "_fbb.CreateVectorOfStructs";
if (field.offset64) {
// This is normal 32-bit vector, with 64-bit addressing.
code += "64<::flatbuffers::Vector>";
code += "64<::flatbuffers::Vector, ::flatbuffers::uoffset_t>";
}
}
code += "(" + value + ")";
Expand Down Expand Up @@ -3576,7 +3576,7 @@ class CppGenerator : public BaseGenerator {
code += "_fbb.CreateVector";
if (field.offset64) {
// This is normal 32-bit vector, with 64-bit addressing.
code += "64<::flatbuffers::Vector>";
code += "64<::flatbuffers::Vector, ::flatbuffers::uoffset_t>";
}
code += "(" + value + ")";
}
Expand Down
6 changes: 3 additions & 3 deletions tests/64bit/offset64_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void Offset64Test() {
// Then serialize all the fields that have 64-bit offsets, as these must be
// serialized before any 32-bit fields are added to the buffer.
const Offset64<Vector<uint8_t>> far_vector_offset =
builder.CreateVector64<Vector>(far_data);
builder.CreateVector64<Vector, uoffset_t>(far_data);

const Offset64<String> far_string_offset =
builder.CreateString<Offset64>("some far string");
Expand Down Expand Up @@ -136,7 +136,7 @@ void Offset64NestedFlatBuffer() {
fbb.Clear();

const Offset64<Vector64<uint8_t>> nested_flatbuffer_offset =
fbb.CreateVector64<Vector64>(nested_data);
fbb.CreateVector64(nested_data);

// Now that we are done with the 64-bit fields, we can create and add the
// normal fields.
Expand Down Expand Up @@ -387,7 +387,7 @@ void Offset64ManyVectors() {
// of putting all 64-bit things at the tail of the buffer.
std::array<Offset64<Vector<int8_t>>, kNumVectors> offsets_64bit;
for (size_t i = 0; i < kNumVectors; ++i) {
offsets_64bit[i] = builder.CreateVector64<Vector>(data);
offsets_64bit[i] = builder.CreateVector64<Vector, uoffset_t>(data);
}

// Create some unrelated, 64-bit offset value for later testing.
Expand Down
12 changes: 6 additions & 6 deletions tests/64bit/test_64bit_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ inline ::flatbuffers::Offset<WrapperTable> CreateWrapperTable(
inline ::flatbuffers::Offset<WrapperTable> CreateWrapperTableDirect(
::flatbuffers::FlatBufferBuilder64 &_fbb,
const std::vector<int8_t> *vector = nullptr) {
auto vector__ = vector ? _fbb.CreateVector64<::flatbuffers::Vector>(*vector) : 0;
auto vector__ = vector ? _fbb.CreateVector64<::flatbuffers::Vector, ::flatbuffers::uoffset_t>(*vector) : 0;
return CreateWrapperTable(
_fbb,
vector__);
Expand Down Expand Up @@ -373,11 +373,11 @@ inline ::flatbuffers::Offset<RootTable> CreateRootTableDirect(
const std::vector<LeafStruct> *big_struct_vector = nullptr,
const std::vector<::flatbuffers::Offset<WrapperTable>> *many_vectors = nullptr,
const std::vector<uint8_t> *forced_aligned_vector = nullptr) {
auto far_vector__ = far_vector ? _fbb.CreateVector64<::flatbuffers::Vector>(*far_vector) : 0;
auto far_vector__ = far_vector ? _fbb.CreateVector64<::flatbuffers::Vector, ::flatbuffers::uoffset_t>(*far_vector) : 0;
auto far_string__ = far_string ? _fbb.CreateString<::flatbuffers::Offset64>(far_string) : 0;
auto big_vector__ = big_vector ? _fbb.CreateVector64(*big_vector) : 0;
auto nested_root__ = nested_root ? _fbb.CreateVector64(*nested_root) : 0;
auto far_struct_vector__ = far_struct_vector ? _fbb.CreateVectorOfStructs64<::flatbuffers::Vector>(*far_struct_vector) : 0;
auto far_struct_vector__ = far_struct_vector ? _fbb.CreateVectorOfStructs64<::flatbuffers::Vector, ::flatbuffers::uoffset_t>(*far_struct_vector) : 0;
auto big_struct_vector__ = big_struct_vector ? _fbb.CreateVectorOfStructs64(*big_struct_vector) : 0;
if (forced_aligned_vector) { _fbb.ForceVectorAlignment64(forced_aligned_vector->size(), sizeof(uint8_t), 32); }
auto forced_aligned_vector__ = forced_aligned_vector ? _fbb.CreateVector64(*forced_aligned_vector) : 0;
Expand Down Expand Up @@ -430,7 +430,7 @@ inline ::flatbuffers::Offset<WrapperTable> CreateWrapperTable(::flatbuffers::Fla
(void)_rehasher;
(void)_o;
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder64 *__fbb; const WrapperTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
auto _vector = _o->vector.size() ? _fbb.CreateVector64<::flatbuffers::Vector>(_o->vector) : 0;
auto _vector = _o->vector.size() ? _fbb.CreateVector64<::flatbuffers::Vector, ::flatbuffers::uoffset_t>(_o->vector) : 0;
return CreateWrapperTable(
_fbb,
_vector);
Expand Down Expand Up @@ -513,13 +513,13 @@ inline ::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBuffe
(void)_rehasher;
(void)_o;
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder64 *__fbb; const RootTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
auto _far_vector = _o->far_vector.size() ? _fbb.CreateVector64<::flatbuffers::Vector>(_o->far_vector) : 0;
auto _far_vector = _o->far_vector.size() ? _fbb.CreateVector64<::flatbuffers::Vector, ::flatbuffers::uoffset_t>(_o->far_vector) : 0;
auto _a = _o->a;
auto _far_string = _o->far_string.empty() ? 0 : _fbb.CreateString<::flatbuffers::Offset64>(_o->far_string);
auto _big_vector = _o->big_vector.size() ? _fbb.CreateVector64(_o->big_vector) : 0;
auto _near_string = _o->near_string.empty() ? 0 : _fbb.CreateString(_o->near_string);
auto _nested_root = _o->nested_root.size() ? _fbb.CreateVector64(_o->nested_root) : 0;
auto _far_struct_vector = _o->far_struct_vector.size() ? _fbb.CreateVectorOfStructs64<::flatbuffers::Vector>(_o->far_struct_vector) : 0;
auto _far_struct_vector = _o->far_struct_vector.size() ? _fbb.CreateVectorOfStructs64<::flatbuffers::Vector, ::flatbuffers::uoffset_t>(_o->far_struct_vector) : 0;
auto _big_struct_vector = _o->big_struct_vector.size() ? _fbb.CreateVectorOfStructs64(_o->big_struct_vector) : 0;
auto _many_vectors = _o->many_vectors.size() ? _fbb.CreateVector<::flatbuffers::Offset<WrapperTable>> (_o->many_vectors.size(), [](size_t i, _VectorArgs *__va) { return CreateWrapperTable(*__va->__fbb, __va->__o->many_vectors[i].get(), __va->__rehasher); }, &_va ) : 0;
_fbb.ForceVectorAlignment64(_o->forced_aligned_vector.size(), sizeof(uint8_t), 32);
Expand Down

0 comments on commit 8989319

Please sign in to comment.