Skip to content

Instantly share code, notes, and snippets.

@Nekrolm
Last active November 23, 2020 15:22
Show Gist options
  • Save Nekrolm/1e65a60b4862deca81d9d22c62f575dc to your computer and use it in GitHub Desktop.
Save Nekrolm/1e65a60b4862deca81d9d22c62f575dc to your computer and use it in GitHub Desktop.
cxxconcept17
#pragma once
#include <type_traits>
namespace cxxconcept17 {
namespace detail {
enum class RequiredE { kRequired = 0 };
}
constexpr auto required = detail::RequiredE::kRequired;
template <bool P>
using IsTrue = std::enable_if_t<P, detail::RequiredE>;
template <bool P>
using IsFalse = std::enable_if_t<!P, detail::RequiredE>;
template <class T, class U>
using IsSameAs = IsTrue<std::is_same_v<T, U>>;
template <class... ConceptApplied>
using Conjunction = std::common_type_t<detail::RequiredE, ConceptApplied...>;
namespace detail {
template <class T, template <class> class Concept, class = void>
struct is_concept_satisfied_impl : std::false_type {};
template <class T, template <class> class Concept>
struct is_concept_satisfied_impl<T, Concept,
decltype(void(std::declval<Concept<T>>()))>
: std::true_type {};
} // namespace detail
template <class T, template <class> class Concept>
struct is_concept_satisfied : detail::is_concept_satisfied_impl<T, Concept> {};
template <class T, template <class> class Concept>
constexpr bool is_concept_satisfied_v = is_concept_satisfied<T, Concept>::value;
template <class T, template <class> class... Concepts>
using IsSatisfiedAnyOf = IsTrue<(is_concept_satisfied_v<T, Concepts> || ...)>;
template <class T, template <class> class... Concepts>
using IsSatisfiedAllOf = IsTrue<(is_concept_satisfied_v<T, Concepts> && ...)>;
template <class T, template <class> class... Concepts>
using IsSatisfiedOneOf =
IsTrue<(static_cast<int>(is_concept_satisfied_v<T, Concepts>) + ...) == 1>;
template <class T, template <class> class Concept>
using IsNotSatisfied = IsFalse<is_concept_satisfied_v<T, Concept>>;
template <class T, template <class> class Concept>
using IsSatisfied = IsTrue<is_concept_satisfied_v<T, Concept>>;
template <class T>
struct identity {
using type = T;
};
template <class T>
using identity_t = typename identity<T>::type;
template <class From, class To>
using IsConvertible = IsTrue<std::is_convertible_v<From, To>>;
template <class T, class... Args>
using IsConstructible = IsTrue<std::is_constructible_v<T, Args...>>;
} // namespace cxxconcept17
#include <vector>
#include "cxxconcept17.hpp"
namespace cp17 = cxxconcept17;
namespace impl {
template <class T>
using IsIncrementable =
cp17::IsSameAs<T, std::decay_t<decltype(++std::declval<T&>())>>;
template <class T, class To>
using IsEqualComparableTo = cp17::IsSameAs<
bool, std::decay_t<decltype(std::declval<T>() != std::declval<To>())>>;
template <class T, template <class> class Concept,
class Begin = std::decay_t<decltype(std::begin(std::declval<T>()))>,
class End = std::decay_t<decltype(std::end(std::declval<T>()))>,
class Elem = std::decay_t<decltype(*std::declval<Begin>())>>
using IsInputRangeOf =
cp17::Conjunction<IsIncrementable<Begin>, IsEqualComparableTo<Begin, End>,
Concept<Elem>>;
} // namespace impl
template <class T, template <class> class Concept>
using IsInputRangeOf = impl::IsInputRangeOf<T, Concept>;
namespace impl {
template <class T, class Sum = std::decay_t<decltype(std::declval<T&>() +=
std::declval<T>())>>
using IsAddable = cp17::IsSameAs<T, Sum>;
}
template <class T>
using IsAddable = impl::IsAddable<T>;
template <class V, IsInputRangeOf<V, IsAddable> = cp17::required>
auto sum(const V& v, std::decay_t<decltype(*std::begin(v))> init) {
for (auto&& x : v) {
init += x;
}
return init;
}
static_assert(cp17::is_concept_satisfied_v<int, IsAddable>);
static_assert(!cp17::is_concept_satisfied_v<std::vector<int>, IsAddable>);
template <class T>
using IsInputRangeOfAddable = IsInputRangeOf<T, IsAddable>;
static_assert(
cp17::is_concept_satisfied_v<std::vector<int>, IsInputRangeOfAddable>);
template <class T>
using IsAddableOrRangeOfAddable =
cp17::IsSatisfiedAnyOf<T, IsAddable, IsInputRangeOfAddable>;
static_assert(cp17::is_concept_satisfied_v<float, IsAddableOrRangeOfAddable>);
static_assert(cp17::is_concept_satisfied_v<std::vector<float>,
IsAddableOrRangeOfAddable>);
int main() {
std::vector<float> v;
std::vector<std::vector<int>> vv;
sum(v, 0);
// CE: sum(vv, {});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment