Created
September 25, 2018 07:29
-
-
Save btaczala/405ee665a09a071513362c7e79460d70 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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