Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Type class: filterable. For explanation, see: http://functionalcpp.wordpress.com/2013/09/18/type-class-filterable/
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
#pragma once
#include <deque>
#include <list>
#include <set>
#include <string>
#include <unordered_set>
#include <vector>
namespace fc
{
template <class C>
struct container_traits
{
// Type value_type
// void add_element(C&,T)
// void concat(C&,C)
// Type rebind<U>
};
template<class C>
struct sequence_container_traits;
template<template<class,class> class C, class T, class A>
struct sequence_container_traits<C<T,A>>
{
using value_type = T;
static void add_element(C<T,A>& c, const T& t)
{
c.push_back(t);
}
static void concat(C<T,A>& lhs, const C<T,A>& rhs)
{
lhs.insert(lhs.end(),rhs.begin(),rhs.end());
}
template<class U>
using rebind = C<U,typename A::template rebind<U>::other>;
};
template<class... Args>
struct container_traits<std::deque<Args...>> : public sequence_container_traits<std::deque<Args...>>
{};
template<class... Args>
struct container_traits<std::list<Args...>> : public sequence_container_traits<std::list<Args...>>
{};
template<class... Args>
struct container_traits<std::vector<Args...>> : public sequence_container_traits<std::vector<Args...>>
{};
template<class C>
struct associative_container_traits;
template<template<class,class,class> class C, class T, template<class> class O, class A>
struct associative_container_traits<C<T,O<T>,A>>
{
using value_type = T;
static void add_element(C<T,O<T>,A>& c, const T& t)
{
c.insert(t);
}
static void concat(C<T,O<T>,A>& lhs, const C<T,O<T>,A>& rhs)
{
lhs.insert(rhs.begin(),rhs.end());
}
template<class U>
using rebind = C<U,O<U>,typename A::template rebind<U>::other>;
};
template<class... Args>
struct container_traits<std::multiset<Args...>> : public associative_container_traits<std::multiset<Args...>>
{};
template<class... Args>
struct container_traits<std::set<Args...>> : public associative_container_traits<std::set<Args...>>
{};
template<class C>
struct hash_container_traits;
template<template<class,class,class,class> class C, class T, template<class> class H, template<class> class O, class A>
struct hash_container_traits<C<T,H<T>,O<T>,A>>
{
using value_type = T;
static void add_element(C<T,H<T>,O<T>,A>& c, const T& t)
{
c.insert(t);
}
static void concat(C<T,H<T>,O<T>,A>& lhs, const C<T,H<T>,O<T>,A>& rhs)
{
lhs.insert(rhs.begin(),rhs.end());
}
template<class U>
using rebind = C<U,H<U>,O<U>,typename A::template rebind<U>::other>;
};
template<class... Args>
struct container_traits<std::unordered_multiset<Args...>> : public hash_container_traits<std::unordered_multiset<Args...>>
{};
template<class... Args>
struct container_traits<std::unordered_set<Args...>> : public hash_container_traits<std::unordered_set<Args...>>
{};
// basic_string
template<class C>
struct string_container_traits;
template<template<class,class,class> class C, class T, template<class> class K, class A>
struct string_container_traits<C<T,K<T>,A>>
{
using value_type = T;
static void add_element(C<T,K<T>,A>& c, const T& t)
{
c.push_back(t);
}
static void concat(C<T,K<T>,A>& lhs, const C<T,K<T>,A>& rhs)
{
lhs+=rhs;
}
template<class U>
using rebind = C<U,K<U>,typename A::template rebind<U>::other>;
};
template<class... Args>
struct container_traits<std::basic_string<Args...>> : public string_container_traits<std::basic_string<Args...>>
{};
}
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
#pragma once
#include <type_traits>
#include <utility>
namespace fc
{
template<
class F, class... Args,
class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type,
class = typename std::enable_if<!std::is_member_object_pointer<F>::value>::type
>
auto eval(F&& f, Args&&... args) -> decltype(f(std::forward<Args>(args)...))
{
return f(std::forward<Args>(args)...);
}
template<class R, class C, class... Args>
auto eval(R(C::*f)() const, const C& c, Args&&... args) -> R
{
return (c.*f)(std::forward<Args>(args)...);
}
template<class R, class C, class... Args>
auto eval(R(C::*f)() const, C& c, Args&&... args) -> R
{
return (c.*f)(std::forward<Args>(args)...);
}
template<class R, class C, class... Args>
auto eval(R(C::*f)(), C& c, Args&&... args) -> R
{
return (c.*f)(std::forward<Args>(args)...);
}
template<class R, class C>
auto eval(R(C::*m), const C& c) -> const R&
{
return c.*m;
}
template<class R, class C>
auto eval(R(C::*m), C& c) -> R&
{
return c.*m;
}
}
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
#pragma once
#include "foldable.h"
namespace fc
{
template<class T>
struct filterable // : foldable
{
// Type value_type
// filterable<A> filter(bool(A),filterable<A>)
static constexpr bool is_instance = false;
};
// Convenience functions
template<class F, class T>
auto filter(F&& f, const T& in)
{
return filterable<T>::filter(std::forward<F>(f),in);
}
// container instances
template<class T>
struct default_container_filterable : public foldable<T>
{
// Type value_type
using value_type = typename ::fc::container_traits<T>::value_type;
// filterable<A> filter(bool(A),filterable<A>)
template<class F>
static auto filter(F&& f, const T& in) -> T
{
T out;
for (auto& a : in)
if (::fc::eval(f,a))
::fc::container_traits<T>::add_element(out,a);
return out;
}
static constexpr bool is_instance = false;
};
#define FC_DEFAULT_CONTAINER_FILTERABLE(T)\
template<class... Args>\
struct filterable<T<Args...>> : public default_container_filterable<T<Args...>>\
{};
FC_DEFAULT_CONTAINER_FILTERABLE(std::deque);
FC_DEFAULT_CONTAINER_FILTERABLE(std::list);
FC_DEFAULT_CONTAINER_FILTERABLE(std::multiset);
FC_DEFAULT_CONTAINER_FILTERABLE(std::set);
FC_DEFAULT_CONTAINER_FILTERABLE(std::basic_string);
FC_DEFAULT_CONTAINER_FILTERABLE(std::unordered_multiset);
FC_DEFAULT_CONTAINER_FILTERABLE(std::unordered_set);
FC_DEFAULT_CONTAINER_FILTERABLE(std::vector);
}
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
#pragma once
#include <memory>
#include "container_traits.h"
#include "eval.h"
#include "monoid.h"
namespace fc
{
template<class T>
struct foldable
{
// Type value_type
// A fold(foldable<A>) requires monoid<A>
// B lfold(B(B,A),B,foldable<A>)
static constexpr bool is_instance = false;
};
// Convenience functions
template<class T>
auto fold(const T& in)
{
return foldable<T>::fold(in);
}
template<class F, class B, class T>
auto lfold(F&& f, B&& b, const T& in)
{
return foldable<T>::lfold(std::forward<F>(f),std::forward<B>(b),in);
}
// shared_ptr instance
template<class T>
struct foldable<std::shared_ptr<T>>
{
// Type value_type
using value_type = T;
// A fold(foldable<A>) requires monoid<A>
template<
class T_,
class = typename std::enable_if<std::is_same<T,T_>::value>,
class = typename std::enable_if<monoid<T>::is_instance>::type>
static auto fold(const T_& in)
{
if (in)
return monoid<T>::append(monoid<T>::empty(),*in);
return monoid<T>::empty();
}
// B lfold(B(B,A),B,foldable<A>)
template<class F, class B>
static auto lfold(F&& f, B b, const std::shared_ptr<T>& in) -> B
{
if (in)
b = eval(f,b,*in);
return b;
}
static constexpr bool is_instance = true;
};
// container instances
template<class T>
struct default_container_foldable
{
// Type value_type
using value_type = typename container_traits<T>::value_type;
// A fold(foldable<A>) requires monoid<A>
template<
class T_,
class = typename std::enable_if<std::is_same<T,T_>::value>,
class = typename std::enable_if<monoid<typename container_traits<T_>::value_type>::is_instance>::type>
static auto fold(const T_& in)
{
using A = typename container_traits<T_>::value_type;
return lfold(monoid<A>::append,monoid<A>::empty(),in);
}
// B lfold(B(B,A),B,foldable<A>)
template<class F, class B>
static auto lfold(F&& f, B b, const T& in) -> B
{
for (auto& a : in)
b = eval(f,b,a);
return b;
}
static constexpr bool is_instance = true;
};
#define FC_DEFAULT_CONTAINER_FOLDABLE(T)\
template<class... Args>\
struct foldable<T<Args...>> : public default_container_foldable<T<Args...>>\
{};
FC_DEFAULT_CONTAINER_FOLDABLE(std::deque);
FC_DEFAULT_CONTAINER_FOLDABLE(std::list);
FC_DEFAULT_CONTAINER_FOLDABLE(std::multiset);
FC_DEFAULT_CONTAINER_FOLDABLE(std::set);
FC_DEFAULT_CONTAINER_FOLDABLE(std::basic_string);
FC_DEFAULT_CONTAINER_FOLDABLE(std::unordered_multiset);
FC_DEFAULT_CONTAINER_FOLDABLE(std::unordered_set);
FC_DEFAULT_CONTAINER_FOLDABLE(std::vector);
}
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
// Build using -std=gnu++1y
#include <iostream>
#include <functional>
#include <locale>
#include "foldable.h"
#include "filterable.h"
#include "mappable.h"
#include "monoid.h"
#include "rfoldable.h"
#include "zip.h"
struct Person
{
std::string name;
int age;
double income;
};
double mean_20s_income(const std::vector<Person>& people)
{
auto in_20s = [](const Person& p){return p.age < 30 && p.age >= 20;};
auto get_mean = [n=0](double last_mean, double income) mutable
{
++n;
return last_mean*(n-1)/n + (double)income/n;
};
return fc::lfold(get_mean,0.0,fc::map(&Person::income,fc::filter(in_20s,people)));
}
int main()
{
std::vector<int> numbers{0,1,2,3,4,5,6,7,8,9,10};
// filter using lfold
auto append_even = [](std::vector<int> ns, int n)
{
if (n % 2 == 0) ns.push_back(n);
return ns;
};
for (int n : fc::lfold(append_even,std::vector<int>{},numbers))
std::cout << n << " ";
std::cout << "\n";
// filter using map and fold
auto to_even_vector = [](int n){
if (n % 2 == 0)
return std::vector<int>{n};
return std::vector<int>{};
};
for (int n : fc::fold(fc::map(to_even_vector,numbers)))
std::cout << n << " ";
std::cout << "\n";
// filter
auto is_even = [](int n){return n % 2 == 0;};
for (int n : fc::filter(is_even,numbers))
std::cout << n << " ";
std::cout << "\n";
// stuff
std::vector<Person> people{
{"Ashley",19,10.5},
{"Betty",22,15},
{"Chris",23,17.25},
{"Daniel",27,31}, // <- balling
{"Elissa",30,22},
{"Frank",24,16}
};
std::cout << "mean income " << mean_20s_income(people) << "\n";
return 0;
}
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
#pragma once
#include <memory>
#include "container_traits.h"
#include "tuple.h"
#include "tuple_eval.h"
namespace fc
{
// remove const, volatile and references
template<class T>
using remove_cv_ref = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template<class T>
struct mappable
{
// Type value_type
// mappable<R> map(R(A),mappable<A>)
static constexpr bool is_instance = false;
};
// Convenience functions
template<class F, class T, class... Args>
auto map(F&& f, const T& in, const Args&... args)
{
return mappable<T>::map(std::forward<F>(f),in,args...);
}
// Function instances
template<class Result,class... Params>
struct mappable<Result(Params...)>
{
// Type value_type
using value_type = Result;
// mappable<R> map(R(A,Args...),mappable<A>,mappable<Args>...)
template<class F,class A,class... Args>
static auto map(F&& f, const A& in, const Args&... args)
{
auto t_funcs = std::make_tuple(in,args...);
return [f,t_funcs](Params... params)
{
return tuple_eval(f,
multi_tuple_eval(t_funcs,std::forward_as_tuple(params...))
);
};
}
static constexpr bool is_instance = true;
};
// const member function
template<class Result, class Class, class... Params>
struct mappable<Result(Class::*)(Params...) const> :
public mappable<Result(const Class&,Params...)>
{};
// member function
template<class Result, class Class, class... Params>
struct mappable<Result(Class::*)(Params...)> :
public mappable<Result(Class&,Params...)>
{};
// member object
template<class Result, class Class>
struct mappable<Result(Class::*)> :
public mappable<Result(const Class&)>
{};
// free function
template<class Result, class... Params>
struct mappable<Result(*)(Params...)> :
public mappable<Result(Params...)>
{};
// shared_ptr instance
template<class T>
struct mappable<std::shared_ptr<T>>
{
// Type value_type
using value_type = T;
// mappable<R> map(R(A,Args...),mappable<A>,mappable<Args>...)
template<class F,class A,class... Args>
static auto map(F&& f, const std::shared_ptr<A>& in, const std::shared_ptr<Args>&... args)
-> std::shared_ptr<remove_cv_ref<decltype(eval(f,*in,(*args)...))>>
{
if (!tuple_all_valid(std::forward_as_tuple(in,args...)))
return std::shared_ptr<remove_cv_ref<decltype(eval(f,*in,(*args)...))>>();
return std::make_shared<remove_cv_ref<decltype(eval(f,*in,(*args)...))>>(
std::move(eval(std::forward<F>(f),*in,(*args)...)));
}
static constexpr bool is_instance = true;
};
// container instances
template<class T>
struct default_container_mappable
{
// Type value_type
using value_type = typename container_traits<T>::value_type;
// mappable<R> map(R(A,Args...),mappable<A>,mappable<Args>...)
template<class F,class A,class... Args>
static auto map(F&& f, const A& in, const Args&... args)
-> typename container_traits<T>::template rebind<
remove_cv_ref<decltype(eval(f,
std::declval<typename container_traits<A>::value_type>(),
std::declval<typename container_traits<Args>::value_type>()...
))>>
{
using B = remove_cv_ref<decltype(eval(f,
std::declval<typename container_traits<A>::value_type>(),
std::declval<typename container_traits<Args>::value_type>()...
))>;
using T_B = typename container_traits<T>::template rebind<B>;
T_B out;
const auto ends = std::make_tuple(in.end(),(args.end())...);
for (auto iters = std::make_tuple(in.begin(),(args.begin())...);
!tuple_any_equal(iters,ends);
tuple_increment(iters))
{
container_traits<T_B>::add_element(out,tuple_eval(std::forward<F>(f),tuple_dereference(iters)));
}
return out;
}
static constexpr bool is_instance = true;
};
#define FC_DEFAULT_CONTAINER_MAPPABLE(T)\
template<class... Args>\
struct mappable<T<Args...>> : public default_container_mappable<T<Args...>>\
{};
FC_DEFAULT_CONTAINER_MAPPABLE(std::deque);
FC_DEFAULT_CONTAINER_MAPPABLE(std::list);
FC_DEFAULT_CONTAINER_MAPPABLE(std::multiset);
FC_DEFAULT_CONTAINER_MAPPABLE(std::set);
FC_DEFAULT_CONTAINER_MAPPABLE(std::basic_string);
FC_DEFAULT_CONTAINER_MAPPABLE(std::unordered_multiset);
FC_DEFAULT_CONTAINER_MAPPABLE(std::unordered_set);
FC_DEFAULT_CONTAINER_MAPPABLE(std::vector);
}
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
#pragma once
#include "container_traits.h"
namespace fc
{
template<class T>
struct monoid
{
// T empty()
// T append(T,T)
static constexpr bool is_instance = false;
};
// Convenience functions
template<class T>
T append(const T& lhs, const T& rhs)
{
return monoid<T>::append(lhs,rhs);
}
// Fundamental type instances
template<class T>
struct default_fundamental_type_monoid
{
static T empty(){return T{};}
static T append(const T& lhs, const T& rhs){return lhs+rhs;}
static constexpr bool is_instance = true;
};
#define FUNDAMENTAL_TYPES\
X(bool)\
X(signed char)\
X(unsigned char)\
X(char)\
X(wchar_t)\
X(char16_t)\
X(char32_t)\
X(short)\
X(unsigned short)\
X(int)\
X(unsigned)\
X(long)\
X(unsigned long)\
X(long long)\
X(unsigned long long)
#define FC_DEFAULT_FUNDAMENTAL_TYPE_MONOID(T)\
template<>\
struct monoid<T> : public default_fundamental_type_monoid<T>\
{};
#define X FC_DEFAULT_FUNDAMENTAL_TYPE_MONOID
FUNDAMENTAL_TYPES;
#undef X
// Container instances
template<class T>
struct default_container_monoid
{
// T empty()
static T empty(){return T{};}
// T append(T,T)
static T append(T lhs, const T& rhs)
{
container_traits<T>::concat(lhs,rhs);
return lhs;
}
static constexpr bool is_instance = true;
};
#define FC_DEFAULT_CONTAINER_MONOID(T)\
template<class... Args>\
struct monoid<T<Args...>> : public default_container_monoid<T<Args...>>\
{};
FC_DEFAULT_CONTAINER_MONOID(std::deque);
FC_DEFAULT_CONTAINER_MONOID(std::list);
FC_DEFAULT_CONTAINER_MONOID(std::multiset);
FC_DEFAULT_CONTAINER_MONOID(std::set);
FC_DEFAULT_CONTAINER_MONOID(std::basic_string);
FC_DEFAULT_CONTAINER_MONOID(std::unordered_multiset);
FC_DEFAULT_CONTAINER_MONOID(std::unordered_set);
FC_DEFAULT_CONTAINER_MONOID(std::vector);
}
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
#pragma once
#include "foldable.h"
namespace fc
{
template<class T>
struct rfoldable // : foldable
{
// Type value_type
// B rfold(B(A,B),B,foldable<A>)
static constexpr bool is_instance = false;
};
// Convenience functions
template<class F, class B, class T>
auto rfold(F&& f, B&& b, const T& in)
{
return rfoldable<T>::rfold(std::forward<F>(f),std::forward<B>(b),in);
}
// shared_ptr instance
template<class T>
struct rfoldable<std::shared_ptr<T>> : public foldable<std::shared_ptr<T>>
{
// Type value_type
using value_type = T;
// B rfold(B(A,B),B,foldable<A>)
template<class F, class B>
static auto rfold(F&& f, B b, const std::shared_ptr<T>& in) -> B
{
if (in)
b = ::fc::eval(f,b,*in);
return b;
}
static constexpr bool is_instance = true;
};
// container instances
template<class T>
struct default_container_rfoldable : public foldable<T>
{
// Type value_type
using value_type = typename ::fc::container_traits<T>::value_type;
// B rfold(B(A,B),B,foldable<A>)
template<class F, class B>
static auto rfold(F&& f, B b, const T& in) -> B
{
for (auto a_it = in.rbegin(); a_it != in.rend(); ++a_it)
b = ::fc::eval(f,*a_it,b);
return b;
}
static constexpr bool is_instance = true;
};
#define FC_DEFAULT_CONTAINER_RFOLDABLE(T)\
template<class... Args>\
struct rfoldable<T<Args...>> : public default_container_rfoldable<T<Args...>>\
{};
FC_DEFAULT_CONTAINER_RFOLDABLE(std::deque);
FC_DEFAULT_CONTAINER_RFOLDABLE(std::list);
FC_DEFAULT_CONTAINER_RFOLDABLE(std::multiset);
FC_DEFAULT_CONTAINER_RFOLDABLE(std::set);
FC_DEFAULT_CONTAINER_RFOLDABLE(std::basic_string);
FC_DEFAULT_CONTAINER_RFOLDABLE(std::unordered_multiset);
FC_DEFAULT_CONTAINER_RFOLDABLE(std::unordered_set);
FC_DEFAULT_CONTAINER_RFOLDABLE(std::vector);
}
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
#pragma once
#include <tuple>
namespace fc
{
template<size_t index>
struct tuple_helper
{
template<class... Args>
static bool any_equal(const std::tuple<Args...>& lhs, const std::tuple<Args...>& rhs)
{
if (std::get<index>(lhs) == std::get<index>(rhs))
return true;
return tuple_helper<index-1>::any_equal(lhs,rhs);
}
template<class... Args>
static void increment(std::tuple<Args...>& a)
{
tuple_helper<index-1>::increment(a);
std::get<index>(a)++;
}
template<class Tuple,class... Args>
static auto dereference(Tuple&& t, Args&&... args)
{
return tuple_helper<index-1>::dereference(
std::forward<Tuple>(t),
std::get<index>(std::forward<Tuple>(t)),
std::forward<Args>(args)...
);
}
template<class... Args>
static bool all_valid(const std::tuple<Args...>& a)
{
return bool(std::get<index>(a)) && tuple_helper<index-1>::all_valid(a);
}
};
template<>
struct tuple_helper<0>
{
template<class... Args>
static bool any_equal(const std::tuple<Args...>& lhs, const std::tuple<Args...>& rhs)
{
return std::get<0>(lhs) == std::get<0>(rhs);
}
template<class... Args>
static void increment(std::tuple<Args...>& a)
{
std::get<0>(a)++;
}
template<class Tuple,class... Args>
static auto dereference(Tuple&& t, Args&&... args)
{
return std::tuple<decltype(*std::get<0>(t)),decltype(*args)...>(*std::get<0>(t),(*args)...);
}
template<class... Args>
static bool all_valid(const std::tuple<Args...>& a)
{
return bool(std::get<0>(a));
}
};
template<class A,class... Args>
bool tuple_any_equal(const std::tuple<A,Args...>& lhs, const std::tuple<A,Args...>& rhs)
{
return tuple_helper<sizeof...(Args)>::any_equal(lhs,rhs);
}
template<class A,class... Args>
void tuple_increment(std::tuple<A,Args...>& a)
{
tuple_helper<sizeof...(Args)>::increment(a);
}
template<class Tuple>
auto tuple_dereference(Tuple&& t)
{
return tuple_helper<std::tuple_size<typename std::remove_reference<Tuple>::type>::value-1>::dereference(std::forward<Tuple>(t));
}
template<class A,class... Args>
bool tuple_all_valid(const std::tuple<A,Args...>& a)
{
return tuple_helper<sizeof...(Args)>::all_valid(a);
}
}
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
#pragma once
#include <tuple>
#include "eval.h"
namespace fc
{
template<size_t index>
struct tuple_eval_helper
{
template<class Func,class TArgs,class... Args>
static auto evaluate(Func&& f, TArgs&& t_args, Args&&... args)
-> decltype(tuple_eval_helper<index-1>::evaluate(
std::forward<Func>(f),
std::forward<TArgs>(t_args),
std::get<index>(std::forward<TArgs>(t_args)),
std::forward<Args>(args)...
))
{
return tuple_eval_helper<index-1>::evaluate(
std::forward<Func>(f),
std::forward<TArgs>(t_args),
std::get<index>(std::forward<TArgs>(t_args)),
std::forward<Args>(args)...
);
}
};
template<>
struct tuple_eval_helper<0>
{
template<class Func,class TArgs,class... Args>
static auto evaluate(Func&& f, TArgs&& t_args, Args&&... args)
-> decltype(eval(
std::forward<Func>(f),
std::get<0>(std::forward<TArgs>(t_args)),
std::forward<Args>(args)...
))
{
return eval(
std::forward<Func>(f),
std::get<0>(std::forward<TArgs>(t_args)),
std::forward<Args>(args)...
);
}
};
template<class Func,class TArgs>
auto tuple_eval(Func&& f, TArgs&& t_args)
-> decltype(tuple_eval_helper<std::tuple_size<
typename std::remove_reference<TArgs>::type>::value-1>::evaluate(
std::forward<Func>(f),
std::forward<TArgs>(t_args)
))
{
return tuple_eval_helper<std::tuple_size<
typename std::remove_reference<TArgs>::type>::value-1>::evaluate(
std::forward<Func>(f),
std::forward<TArgs>(t_args)
);
}
template<size_t index>
struct multi_tuple_eval_helper
{
template<class TFuncs,class TArgs,class... Results>
static auto evaluate(TFuncs&& t_funcs, TArgs&& t_args, Results&&... results)
-> decltype(multi_tuple_eval_helper<index-1>::evaluate(
std::forward<TFuncs>(t_funcs),
std::forward<TArgs>(t_args),
tuple_eval(std::get<index>(t_funcs),t_args),
std::forward<Results>(results)...
))
{
return multi_tuple_eval_helper<index-1>::evaluate(
std::forward<TFuncs>(t_funcs),
std::forward<TArgs>(t_args),
tuple_eval(std::get<index>(t_funcs),t_args),
std::forward<Results>(results)...
);
}
};
template<>
struct multi_tuple_eval_helper<0>
{
template<class TFuncs,class TArgs,class... Results>
static auto evaluate(TFuncs&& t_funcs, TArgs&& t_args, Results&&... results)
-> decltype(std::tuple<decltype(tuple_eval(std::get<0>(t_funcs),t_args)),Results...>(
tuple_eval(std::get<0>(t_funcs),t_args),
std::forward<Results>(results)...
))
{
return std::tuple<decltype(tuple_eval(std::get<0>(t_funcs),t_args)),Results...>(
tuple_eval(std::get<0>(t_funcs),t_args),
std::forward<Results>(results)...
);
}
};
template<class TFuncs,class TArgs>
auto multi_tuple_eval(TFuncs&& t_funcs, TArgs&& t_args)
-> decltype(multi_tuple_eval_helper<std::tuple_size<
typename std::remove_reference<TFuncs>::type>::value-1>::evaluate(
std::forward<TFuncs>(t_funcs),
std::forward<TArgs>(t_args)
))
{
return multi_tuple_eval_helper<std::tuple_size<
typename std::remove_reference<TFuncs>::type>::value-1>::evaluate(
std::forward<TFuncs>(t_funcs),
std::forward<TArgs>(t_args)
);
}
}
/*
* Copyright (c) 2013, Daniel Park
* All rights reserved.
*
* Permission to modify and redistribute this software is granted to
* anyone provided the above copyright notice, this condition and the
* following disclaimer are retained.
*
* This software is provided "as is", without and express or implied
* warranty. In no event shall the author be liable for damages arising
* from the use of this software.
*/
#pragma once
#include <type_traits>
#include <tuple>
namespace fc
{
struct zipper
{
template<class... Args>
auto operator()(Args&&... args)
{
return std::make_tuple(std::forward<Args>(args)...);
}
};
struct pairer
{
template<class L,class R>
auto operator()(L&& l, R&& r)
{
return std::make_pair(std::forward<L>(l),std::forward<R>(r));
}
};
template<class... Args>
struct zipper_t
{
template<class... Args_>
auto operator()(Args_&&... args)
{
return std::tuple<Args...>(std::forward<Args_>(args)...);
}
};
template<class L,class R>
struct pairer_t
{
template<class L_,class R_>
auto operator()(L_&& l, R_&& r)
{
return std::pair<L,R>(std::forward<L_>(l),std::forward<R_>(r));
}
};
template<class T>
struct make
{
template<class... Args>
auto operator()(Args&&... args)
{
return T(std::forward<Args...>(args...));
}
};
#define FC_BINARY_OPERATORS\
X(plus,+)\
X(minus,-)\
X(multiplies,*)\
X(divides,/)\
X(modulus,%)\
X(equal_to,==)\
X(not_equal_to,!=)\
X(greater,>)\
X(less,<)\
X(greater_equal,>=)\
X(less_equal,<=)\
X(logical_and,&&)\
X(logical_or,||)\
X(bit_and,&)\
X(bit_or,|)\
X(bit_xor,^)
#define X(name,symbol)\
struct name\
{\
template<class L,class R>\
auto operator()(L&& l, R&& r)\
{\
return l symbol r;\
}\
};
FC_BINARY_OPERATORS
#undef X
template<class L,class R>
auto unpair(std::vector<std::pair<L,R>>&& v)
{
std::pair<std::vector<L>,std::vector<R>> out;
for (auto& p : v)
{
out.first.push_back(p.first);
out.second.push_back(p.second);
}
return out;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment