Last active
December 30, 2016 07:54
-
-
Save flisboac/fc34594cd54502fa462bd832085985ba to your computer and use it in GitHub Desktop.
Note: C++11 has a crappy std::array API for constexpr usage. Why, standard bodies? Why?
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
// This is a better version (i think), it does not use std::get(). | |
#include <iostream> | |
#include <array> | |
template <typename T, T T1, T... Ts> | |
struct ConstexprSetHelper { | |
constexpr static size_t size = 1 + sizeof...(Ts); | |
constexpr static bool contains(T elem) { | |
return (elem == T1) || ConstexprSetHelper<T, Ts...>::contains(elem); | |
} | |
constexpr static size_t count(T elem) { | |
return (elem == T1 ? 1 : 0) + ConstexprSetHelper<T, Ts...>::count(elem); | |
} | |
constexpr static T get(size_t index) { | |
return (index < size) | |
? (index == 0) | |
? T1 | |
: ConstexprSetHelper<T, Ts...>::get(index - 1) | |
: T(); | |
} | |
constexpr static size_t indexOf_(T elem, size_t index) { | |
return elem == T1 ? index : ConstexprSetHelper<T, Ts...>::indexOf_(elem, index + 1); | |
} | |
constexpr static size_t indexOf(T elem) { | |
return indexOf_(elem, 0); | |
} | |
}; | |
template <typename T, T T1> | |
struct ConstexprSetHelper<T, T1> { | |
constexpr static size_t size = 1; | |
constexpr static bool contains(T elem) { | |
return (elem == T1); | |
} | |
constexpr static size_t count(T elem) { | |
return (elem == T1 ? 1 : 0); | |
} | |
constexpr static T get(size_t index) { | |
return (index < size) | |
? T1 | |
: T(); | |
} | |
constexpr static size_t indexOf_(T elem, size_t index) { | |
return elem == T1 ? index : ((size_t) -1); | |
} | |
constexpr static size_t indexOf(T elem) { | |
return indexOf_(elem, 0); | |
} | |
}; | |
template <typename T, T... Ts> | |
struct ConstexprSet { | |
constexpr static size_t size = sizeof...(Ts); | |
constexpr static std::array<T, size> values() { | |
return {Ts...}; | |
} | |
constexpr static bool contains(T elem) { | |
return ConstexprSetHelper<T, Ts...>::contains(elem); | |
} | |
constexpr static size_t count(T elem) { | |
return ConstexprSetHelper<T, Ts...>::count(elem); | |
} | |
constexpr static T get(size_t index) { | |
return ConstexprSetHelper<T, Ts...>::get(index); | |
} | |
constexpr static size_t indexOf(T elem) { | |
return ConstexprSetHelper<T, Ts...>::indexOf(elem); | |
} | |
}; | |
template <typename T> | |
struct ConstexprSet<T> { | |
constexpr static size_t size = 0; | |
constexpr static std::array<T, 0> values() { | |
return {}; | |
} | |
constexpr static bool contains(T elem) { | |
return false; | |
} | |
constexpr static size_t count(T elem) { | |
return 0; | |
} | |
constexpr static T get(size_t index) { | |
return T(); | |
} | |
}; | |
int main(void) { | |
using MySet = ConstexprSet<int, 1, 2, 4, 8, 4>; | |
std::cout << std::boolalpha; | |
std::cout << MySet::size << std::endl; | |
std::cout << MySet::contains(2) << std::endl; | |
std::cout << (!MySet::contains(5)) << std::endl; | |
std::cout << ( MySet::count(4) == 2) << std::endl; | |
std::cout << ( MySet::get(2) == 4) << std::endl; | |
std::cout << ( MySet::indexOf(8) == 3) << std::endl; | |
std::cout << ( MySet::indexOf(9) == ((size_t) -1)) << std::endl; | |
return 0; | |
} |
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 <array> | |
#include <iostream> | |
#include <climits> | |
template <typename ET, ET E1, ET... En> | |
struct TemplateArgsSize_ { | |
constexpr static size_t value = 1 + TemplateArgsSize_<ET, En...>::value; | |
}; | |
template <typename ET, ET E1> | |
struct TemplateArgsSize_<ET, E1> { | |
constexpr static size_t value = 1; | |
}; | |
template <typename T, size_t size, size_t index = size - 1> | |
struct StdArrayContains_ { | |
constexpr static inline bool contains(T elem, const std::array<T, size>& array) { | |
return std::get<index>(array) == elem || StdArrayContains_<T, size, index - 1>::contains(elem, array); | |
} | |
}; | |
template <typename T, size_t size> | |
struct StdArrayContains_<T, size, 0> { | |
constexpr static inline bool contains(T elem, const std::array<T, size>& array) { | |
return std::get<0>(array) == elem; | |
} | |
}; | |
template <typename ET, ET E1, ET... En> | |
struct TemplateArgs_ { | |
constexpr static auto size = TemplateArgsSize_<ET, E1, En...>::value; | |
// Some query/getter methods | |
constexpr static std::array<ET, size> values() { | |
return {E1, En...}; | |
} | |
constexpr static bool contains(ET elem) { | |
return StdArrayContains_<ET, size>::contains(elem, values()); | |
//return contains_<size - 1>(elem, values()); // Compile-time stack overflow. DO NOT USE. | |
return true; | |
} | |
template <size_t index> | |
constexpr static bool contains_(ET elem, const std::array<ET, size>& elems) { | |
return (std::get<index>(elems) == elem) // Any other suggestions (alternative constexpr operator[] working in C++11) ? | |
? true | |
: (index > 0) | |
? contains_<index - 1>(elem, elems) | |
: false; | |
} | |
// Some methods used for testing | |
template <typename CharT, typename CharTraits> | |
static inline std::basic_ostream<CharT, CharTraits>& | |
print(std::basic_ostream<CharT, CharTraits>& os) { | |
os << "Size: " << size << std::endl; | |
os << "Elements: {"; | |
const char* sep = ""; | |
for (auto& elem : values()) { | |
os << sep << elem; | |
sep = ", "; | |
} | |
os << "}" << std::endl; | |
return os; | |
} | |
template <typename CharT, typename CharTraits> | |
static inline std::basic_ostream<CharT, CharTraits>& | |
printContains(ET elem, std::basic_ostream<CharT, CharTraits>& os) { | |
os | |
<< "Contains the element '" << elem << "'? " | |
<< contains(elem) << std::endl; | |
return os; | |
} | |
}; | |
int main(void) { | |
using Type = int; | |
using TemplateArgs = TemplateArgs_<Type, 1, 2, 4, 8>; | |
constexpr Type validElem = 2, invalidElem = 5; | |
// Testing | |
std::cout << std::boolalpha; | |
TemplateArgs::printContains(validElem, std::cout); | |
TemplateArgs::printContains(invalidElem, std::cout); | |
TemplateArgs::print(std::cout); | |
static_assert(TemplateArgs::contains(validElem), ""); | |
static_assert(TemplateArgs::contains(invalidElem), "WORKING! WOOO-HOOOO!!!"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment