It would be nice if there was something like tuple but that didn't actually construct the types, but just held them as template parameters, with the features of std::tuple
, the indexing and such. Is there something like tuple that doesn't actually need to construct the objects? And you do something like get the type instead of the object with std::get<0>(tuple)
. Sometimes tuples need to be constexpr
for constexpr
and consteval
evaluation and it won't work if any tuple members are not constexpr
. For example if I add a constructor to one of my tuple members it doesn't compile anymore.
#include <tuple>
#include <cstdint>
#include <cstdio>
#include <array>
#include <tuple>
template <uint32_t N>
struct BitfieldBits
{
constexpr static inline uint64_t num_bits = N;
};
struct DepthMode : BitfieldBits<2>
{
};
struct UseCulling : BitfieldBits<1>
{
};
struct VertexShaderID : BitfieldBits<8>
{
};
template <typename ... T>
struct MyBitfield
{
uint64_t bitfield;
/* HERE, IS THERE A WAY TO HOLD THE TYPES BUT WITHOUT THE ACTUAL OBJECTS */
constexpr static inline std::tuple<T...> tuple{};
constexpr static inline std::array<uint32_t, sizeof ... (T)> bit_shift_offsets = []() consteval
{
std::array<uint32_t, sizeof ... (T)> arr;
auto lambda = [&] <int offset, int idx>(const auto& self) consteval
{
if constexpr (idx >= sizeof ... (T))
return;
else
{// SO I CAN ACCESS IT HERE THROUGH A 'TYPE' std::get<idx>(tuple)::num_bits
arr[idx] = offset;
self.template operator()<offset + std::get<idx>(tuple).num_bits, idx + 1> (self);
}
};
lambda.template operator() <0, 0> (lambda);
return arr;
}();
};
int main(int argc, char* argv[])
{
MyBitfield<DepthMode, UseCulling, VertexShaderID> my_bitfield;
constexpr auto offset = my_bitfield.bit_shift_offsets[2];
}
Also, I'm aware that passing variadic arguments to template parameters (as a parameter pack) is kind of like its own tuple, but it's limited, such as not being able to index into it.
And you do something like get the type instead of the object with
std::get<0>(tuple)
Yes, you can use std::tuple_element_t<0, std::tuple<T...>>
for that purpose.
Replace the member variable
constexpr static inline std::tuple<T...> tuple{};
with
template<size_t I>
using element_t = std::tuple_element_t<I, std::tuple<T...>>;
and then you can replace
std::get<idx>(tuple).num_bits
with
element_t<idx>::num_bits