Skip to content

Instantly share code, notes, and snippets.

@flisboac
Last active December 30, 2016 07:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flisboac/fc34594cd54502fa462bd832085985ba to your computer and use it in GitHub Desktop.
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 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;
}
#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