Skip to content

Instantly share code, notes, and snippets.

@btaczala
Created September 25, 2018 07:29
Show Gist options
  • Save btaczala/405ee665a09a071513362c7e79460d70 to your computer and use it in GitHub Desktop.
Save btaczala/405ee665a09a071513362c7e79460d70 to your computer and use it in GitHub Desktop.
#include <atomic>
#include <bitset>
#include <iostream>
#include <tuple>
#include <type_traits>
namespace details {
template <typename... Args>
unsigned long long getULL(Args... as) {
using unused = int[];
unsigned long long ret{0ULL};
(void)unused{0, (ret <<= 1, ret |= (as ? 1ULL : 0ULL), 0)...};
return ret;
}
template <class T, class Tuple>
struct Index;
template <class T, class... Types>
struct Index<T, std::tuple<T, Types...>> {
static const std::size_t value = 0;
};
template <class T, class U, class... Types>
struct Index<T, std::tuple<U, Types...>> {
static const std::size_t value = 1 + Index<T, std::tuple<Types...>>::value;
};
template <typename T, typename U>
struct has_type : std::false_type {};
template <typename T, typename... Types>
struct has_type<T, std::tuple<T, Types...>> : std::true_type {};
template <typename T, typename U, typename... Types>
struct has_type<T, std::tuple<U, Types...>> : has_type<U, Types...> {};
} // namespace details
namespace tags {
struct Car {};
struct Truck {};
using Tags = std::tuple<Car, Truck>;
} // namespace tags
template <typename T>
using tup_size = std::tuple_size<T>;
template <typename Tuple>
struct StrictBitset {
static_assert(std::tuple_size<Tuple>::value != 1);
template <typename T, typename = typename std::enable_if<
std::is_integral<T>::value &&
!std::is_same<T, bool>::value>::type>
StrictBitset(T&& t) : _bits(t) {
static_assert(sizeof(t) * 8 > std::tuple_size<Tuple>::value, "");
}
StrictBitset(const StrictBitset& lhs) = default;
template <typename... Bools>
StrictBitset(Bools&&... bools) : _bits(details::getULL(bools...)) {
using InnerTuple = std::tuple<Bools...>;
static_assert(
tup_size<InnerTuple>::value == tup_size<tags::Tags>::value,
"Incorrect number of boolean values");
}
template <typename T>
bool test() const {
static_assert(details::has_type<T, Tuple>::value,
"Type T is not regitered in tuple");
constexpr auto index = details::Index<T, Tuple>::value;
return _bits.test(index);
}
template <typename T>
void set(bool value) {
constexpr auto index = details::Index<T, Tuple>::value;
_bits.set(index, value);
}
private:
std::bitset<std::tuple_size<Tuple>::value> _bits;
};
template <typename T>
void foo(typename T::type t)
{}
void foo(int) {}
int main(int argc, char* []) {
{
StrictBitset<tags::Tags> t{false, true};
t.set<tags::Car>(argc == 1);
printf("%d", t.test<tags::Car>());
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment