diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index a2b165fa2..47f93f31f 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -2,11 +2,10 @@ #include #include +#include #include #include -#include -#include namespace mbgl { namespace gl { @@ -143,27 +142,24 @@ void bindAttribute(AttributeLocation location, template class Attributes { public: - using State = std::tuple; + using State = IndexedTuple, TypeList>; using Vertex = detail::Vertex; + template + static constexpr std::size_t Index = TypeIndex::value; + static State state(const ProgramID& id) { return State { { attributeLocation(id, As::name) }... }; } static std::function binder(const State& state) { - return binder(state, std::index_sequence_for()); - } - -private: - template - static std::function binder(const State& state, std::index_sequence) { return [&state] (std::size_t vertexOffset) { - ignore((bindAttribute(std::get(state).location, - std::get(state).count, - std::get(state).type, - sizeof(Vertex), - vertexOffset, - Vertex::attributeOffsets[Is]), 0)...); + ignore({ (bindAttribute(state.template get().location, + state.template get().count, + state.template get().type, + sizeof(Vertex), + vertexOffset, + Vertex::attributeOffsets[Index]), 0)... }); }; } }; diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp index df4de0c75..0b303e9d6 100644 --- a/src/mbgl/gl/uniform.hpp +++ b/src/mbgl/gl/uniform.hpp @@ -3,10 +3,10 @@ #include #include #include +#include #include #include -#include namespace mbgl { namespace gl { @@ -63,8 +63,8 @@ UniformLocation uniformLocation(ProgramID, const char * name); template class Uniforms { public: - using State = std::tuple; - using Values = std::tuple; + using State = IndexedTuple, TypeList>; + using Values = IndexedTuple, TypeList>; static State state(const ProgramID& id) { return State { { uniformLocation(id, Us::name) }... }; @@ -72,7 +72,7 @@ public: static std::function binder(State& state, Values&& values_) { return [&state, values = std::move(values_)] () mutable { - ignore((std::get(state) = std::get(values), 0)...); + ignore({ (state.template get() = values.template get(), 0)... }); }; } }; diff --git a/src/mbgl/util/indexed_tuple.hpp b/src/mbgl/util/indexed_tuple.hpp new file mode 100644 index 000000000..110e7dce1 --- /dev/null +++ b/src/mbgl/util/indexed_tuple.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +namespace mbgl { + +template +struct TypeIndex; + +template +struct TypeIndex : std::integral_constant {}; + +template +struct TypeIndex : std::integral_constant::value> {}; + +template class TypeList {}; + +template class IndexedTuple; + +// A tuple of Ts, where individual members can be accessed via `t.get()` for I ∈ Is. +// +// See https://github.com/mapbox/cpp/blob/master/C%2B%2B%20Structural%20Metaprogramming.md +// for motivation. +// +template +class IndexedTuple, TypeList> : public std::tuple { +public: + static_assert(sizeof...(Is) == sizeof...(Ts), "IndexedTuple size mismatch"); + + using std::tuple::tuple; + + template + static constexpr std::size_t Index = TypeIndex::value; + + template + auto& get() { + return std::get>(*this); + } + + template + const auto& get() const { + return std::get>(*this); + } +}; + +} // namespace mbgl