Skip to content

Instantly share code, notes, and snippets.

@neontorrent
Last active January 4, 2019 21:57
Show Gist options
  • Save neontorrent/8bf71994d501ad243a0a9bb3325ef2fa to your computer and use it in GitHub Desktop.
Save neontorrent/8bf71994d501ad243a0a9bb3325ef2fa to your computer and use it in GitHub Desktop.
C++: is_iterable, map
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <type_traits>
template <typename T, typename = void>
struct is_iterable : std::false_type {};
template <typename T>
struct is_iterable<T, std::void_t<decltype(std::begin(std::declval<T&>())),
decltype(std::end(std::declval<T&>())),
decltype(++std::declval<decltype(std::begin(std::declval<T&>()))&>()), // operator ++
decltype(void(*begin(std::declval<T&>()))) //operator *
> > : std::true_type {};
template <typename T>
constexpr bool is_iterable_v = is_iterable<T>::value;
template<typename F, template<typename> typename T, typename A,
typename B = decltype(std::declval<F&>()(std::declval<A&>())),
typename = std::enable_if_t<is_iterable_v<T<A>>>,
typename = decltype(std::declval<T<B>&>().push_back(std::declval<B&>()) )
>
T<B> map(T<A> c, F f) {
T<B> result;
for(A& a: c) {
result.push_back(f(a));
}
return std::move(result);
}
// template<typename F, template<typename> typename T, typename A,
// typename B = std::invoke_result_t<F,A>>
// T<B> map(T<A> c, F f) {
// static_assert(is_iterable<T<A>>::value);
// return T<B>();
// }
// template<typename F, template<typename> typename T, typename A>
// auto map(T<A> c, F f) -> T<decltype(f(std::declval<A>()))> {
// using B = decltype(f(std::declval<A>()));
// static_assert(is_iterable<T<A>>::value);
// return T<B>();
// }
int main()
{
map(std::vector{1,2}, [](auto i){return i+1;});
// map(std::set{1,2}, [](auto i){return i+1;});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment