Created
December 15, 2018 10:38
-
-
Save pnck/e15224ae64f0126a54bbad2994af9043 to your computer and use it in GitHub Desktop.
a compile-time set type with elements unique check
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 <tuple> | |
using ElementType = size_t; | |
template<ElementType ... es> | |
class SetValidator { | |
protected: | |
static inline constexpr auto cs_ = std::make_tuple(es...); | |
template<size_t _i, size_t _j> | |
static constexpr bool cmp_() { | |
if constexpr (_j == _i) { | |
return false; | |
} else { | |
return std::get<_i>(cs_) == std::get<_j>(cs_); | |
} | |
} | |
template<size_t _i, size_t ... Indices> | |
static constexpr bool is_unique() { | |
if constexpr ((0 || ... || cmp_<_i, Indices>())) { | |
return false; | |
} else { | |
return true; | |
} | |
} | |
template<size_t ... I> | |
static constexpr bool helper(std::index_sequence<I...>) { | |
if constexpr ((1 && ... && is_unique<I, I...>())) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
public: | |
static constexpr bool valid() { | |
return helper(std::make_index_sequence<sizeof...(es)>{}); | |
} | |
}; | |
template<ElementType ... es> | |
class RawSet : public SetValidator<es...> {}; | |
template<ElementType ... es> | |
struct RawNSet : public SetValidator<es...> {}; // negative set, exlude elements | |
template<typename T, bool _ = T::valid()> struct NiceSetError; | |
template<template<ElementType ...> class SetType, ElementType ...es> | |
struct NiceSetError<SetType<es...>, false> { | |
static constexpr auto try_() { | |
static_assert(SetType<es...>::valid(), "there is dupplicated elements"); | |
return SetType<es...>{}; | |
}; | |
using type = decltype(try_()); | |
}; | |
template<template<ElementType ...> class SetType, ElementType ...es> | |
struct NiceSetError<SetType<es...>, true> { | |
using type = SetType<es...>; | |
}; | |
template<ElementType ... es> | |
using Set = typename NiceSetError<RawSet<es...>>::type; | |
template<ElementType ... es> | |
using NSet = typename NiceSetError<RawNSet<es...>>::type; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment