Last active
November 23, 2020 15:22
-
-
Save Nekrolm/1e65a60b4862deca81d9d22c62f575dc to your computer and use it in GitHub Desktop.
cxxconcept17
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
#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 |
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 <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