Skip to content

Instantly share code, notes, and snippets.

@plasma-effect
Last active October 8, 2015 14:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save plasma-effect/13c471f3822d89ea0ac8 to your computer and use it in GitHub Desktop.
Save plasma-effect/13c471f3822d89ea0ac8 to your computer and use it in GitHub Desktop.
plasma.ADT
#pragma once
// Copyright plasma-effect 2015
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)
#include<tuple>
#include<utility>
#include<list>
#include<memory>
#include<vector>
#include<type_traits>
#include<boost/variant.hpp>
#ifdef _MSC_VER
#define PLASMA_ADT_TEMPLATE
#else
#define PLASMA_ADT_TEMPLATE template
#endif
namespace plasma_adt
{
struct recursion_tag {};
namespace function_flag
{
template<int N>struct function_flag_t
{
static constexpr int flag = N;
};
constexpr auto recursion_flag = function_flag_t<0b01>();
constexpr auto memoization_flag = function_flag_t<0b10>();
constexpr auto dual_flag = function_flag_t<0b11>();
constexpr auto no_option_flag = function_flag_t<0b00>();
template<int N, int M>constexpr auto operator+(function_flag_t<N>, function_flag_t<M>)
{
return function_flag_t<(N | M)>();
}
template<class>struct is_function_flag :std::false_type {};
template<>struct is_function_flag<function_flag_t<0>> :std::true_type {};
template<>struct is_function_flag<function_flag_t<1>> :std::true_type {};
template<>struct is_function_flag<function_flag_t<2>> :std::true_type {};
template<>struct is_function_flag<function_flag_t<3>> :std::true_type {};
template<class>struct is_tuple :std::false_type {};
template<class... Ts>struct is_tuple<std::tuple<Ts...>> :std::true_type {};
}
template<class... Types>class data_type
{
typedef std::tuple<Types...> template_parameter_tuple;
template<std::size_t Id>using parameter_type = std::tuple_element_t<Id, template_parameter_tuple>;
typedef data_type<Types...> this_type;
template<class>struct container_t;
typedef container_t<std::make_index_sequence<sizeof...(Types)>> container;
typedef std::list<container> list_type;
typedef typename list_type::const_iterator iterator_type;
static list_type instances;
iterator_type iterator_;
data_type(iterator_type ite) :iterator_(ite) {}
template<class T, class = void>struct value_data_t
{
typedef T true_name;
T value_;
value_data_t(T const& v):value_(v){}
value_data_t(value_data_t const&) = default;
value_data_t(value_data_t&&) = default;
value_data_t& operator=(value_data_t const&) = default;
value_data_t& operator=(value_data_t&&) = default;
~value_data_t() = default;
T get_value()const
{
return value_;
}
bool operator==(value_data_t<T>const& rhs)const
{
return value_ == rhs.value_;
}
};
template<class T>struct value_data_t<T, std::enable_if_t<std::is_same<T, recursion_tag>::value>>
{
typedef this_type true_name;
iterator_type iterator_;
value_data_t(true_name const& v) :iterator_(v.iterator_) {}
value_data_t(value_data_t const&) = default;
value_data_t(value_data_t&&) = default;
value_data_t& operator=(value_data_t const&) = default;
value_data_t& operator=(value_data_t&&) = default;
~value_data_t() = default;
this_type get_value()const
{
return this_type(iterator_);
}
bool operator==(value_data_t<T>const& rhs)const
{
return *iterator_ == *rhs.iterator_;
}
};
template<class T>using true_name = typename value_data_t<T>::true_name;
template<std::size_t Id, class T>struct inside_data_t
{
value_data_t<T> value_;
inside_data_t(true_name<T> const& v) :value_(v) {}
inside_data_t() = default;
inside_data_t(inside_data_t const&) = default;
inside_data_t(inside_data_t&&) = default;
inside_data_t& operator=(inside_data_t const&) = default;
inside_data_t& operator=(inside_data_t&&) = default;
~inside_data_t() = default;
template<class ReturnType, class Funcs>
ReturnType function_call(Funcs const& funcs)const
{
return std::get<Id>(funcs)(value_.get_value());
}
template<class ReturnType, class Funcs, class Recursion>
ReturnType recursion_call(Funcs const& funcs, Recursion const& recur)const
{
return std::get<Id>(funcs)(recur, value_.get_value());
}
template<class ReturnType, class Funcs, class Tuple,std::size_t... Is>
ReturnType function_call_with_argument(Funcs const& funcs, Tuple const& arg,std::index_sequence<Is...>)const
{
return std::get<Id>(funcs)(value_.get_value(), std::get<Is>(arg)...);
}
template<class ReturnType, class Funcs, class Recursion, class Tuple, std::size_t... Is>
ReturnType recursion_call_with_argument(Funcs const& funcs,Recursion const& recur, Tuple const& arg, std::index_sequence<Is...>)const
{
return std::get<Id>(funcs)(recur, value_.get_value(), std::get<Is>(arg)...);
}
bool operator==(inside_data_t<Id, T>const& rhs)const
{
return value_ == rhs.value_;
}
};
template<std::size_t Id, class... Ts>struct inside_data_t<Id, std::tuple<Ts...>>
{
std::tuple<value_data_t<Ts>...> value_;
inside_data_t(true_name<Ts>const&... args) :value_(args...) {}
inside_data_t() = default;
inside_data_t(inside_data_t const&) = default;
inside_data_t(inside_data_t&&) = default;
inside_data_t& operator=(inside_data_t const&) = default;
inside_data_t& operator=(inside_data_t&&) = default;
~inside_data_t() = default;
template<class>struct func_t;
template<std::size_t... Is>struct func_t<std::index_sequence<Is...>>
{
template<class ReturnType,class Funcs>
static ReturnType function_call(std::tuple<value_data_t<Ts>...> const& v, Funcs const& funcs)
{
return std::get<Id>(funcs)(std::get<Is>(v).get_value()...);
}
template<class ReturnType, class Funcs,class Recursion>
static ReturnType recursion_call(std::tuple<value_data_t<Ts>...> const& v, Funcs const& funcs,Recursion const& recur)
{
return std::get<Id>(funcs)(recur, std::get<Is>(v).get_value()...);
}
template<class ReturnType, class Funcs,class Tuple,std::size_t... Us>
static ReturnType function_call_with_argument(std::tuple<value_data_t<Ts>...> const& v, Funcs const& funcs, Tuple const& arg, std::index_sequence<Us...>)
{
return std::get<Id>(funcs)(std::get<Is>(v).get_value()..., std::get<Us>(arg)...);
}
template<class ReturnType, class Funcs, class Recursion,class Tuple,std::size_t... Us>
static ReturnType recursion_call_with_argument(std::tuple<value_data_t<Ts>...> const& v, Funcs const& funcs, Recursion const& recur, Tuple const& arg, std::index_sequence<Us...>)
{
return std::get<Id>(funcs)(recur, std::get<Is>(v).get_value()..., std::get<Us>(arg)...);
}
};
typedef func_t<std::make_index_sequence<sizeof...(Ts)>> function_t;
template<class ReturnType, class Funcs>
ReturnType function_call(Funcs const& funcs)const
{
return function_t::PLASMA_ADT_TEMPLATE function_call<ReturnType>(value_, funcs);
}
template<class ReturnType, class Funcs, class Recursion>
ReturnType recursion_call(Funcs const& funcs, Recursion const& recur)const
{
return function_t::PLASMA_ADT_TEMPLATE recursion_call<ReturnType>(value_, funcs, recur);
}
template<class ReturnType, class Funcs, class Tuple, std::size_t... Is>
ReturnType function_call_with_argument(Funcs const& funcs, Tuple const& arg, std::index_sequence<Is...>)const
{
return function_t::PLASMA_ADT_TEMPLATE function_call_with_argument<ReturnType>(value_, funcs, arg, std::index_sequence<Is...>());
}
template<class ReturnType, class Funcs, class Recursion, class Tuple, std::size_t... Is>
ReturnType recursion_call_with_argument(Funcs const& funcs, Recursion const& recur, Tuple const& arg, std::index_sequence<Is...>)const
{
return function_t::PLASMA_ADT_TEMPLATE recursion_call_with_argument<ReturnType>(value_, funcs, recur, arg, std::index_sequence<Is...>());
}
bool operator==(inside_data_t<Id, std::tuple<Ts...>>const& rhs)const
{
return value_ == rhs.value_;
}
bool operator!=(inside_data_t<Id, std::tuple<Ts...>>const& rhs)const
{
return !(value_ == rhs.value_);
}
};
template<std::size_t Id>struct inside_data_t<Id, void>
{
inside_data_t() = default;
inside_data_t(inside_data_t const&) = default;
inside_data_t(inside_data_t&&) = default;
inside_data_t& operator=(inside_data_t const&) = default;
inside_data_t& operator=(inside_data_t&&) = default;
~inside_data_t() = default;
template<class ReturnType, class Funcs>
ReturnType function_call(Funcs const& funcs)const
{
return std::get<Id>(funcs)();
}
template<class ReturnType, class Funcs, class Recursion>
ReturnType recursion_call(Funcs const& funcs, Recursion const& recur)const
{
return std::get<Id>(funcs)(recur);
}
template<class ReturnType, class Funcs, class Tuple, std::size_t... Is>
ReturnType function_call_with_argument(Funcs const& funcs, Tuple const& arg, std::index_sequence<Is...>)const
{
return std::get<Id>(funcs)(std::get<Is>(arg)...);
}
template<class ReturnType, class Funcs, class Recursion, class Tuple, std::size_t... Is>
ReturnType recursion_call_with_argument(Funcs const& funcs, Recursion const& recur, Tuple const& arg, std::index_sequence<Is...>)const
{
return std::get<Id>(funcs)(recur, std::get<Is>(arg)...);
}
bool operator==(inside_data_t<Id, void>const&)const
{
return true;
}
};
template<std::size_t... Is>struct container_t<std::index_sequence<Is...>>
{
boost::variant<inside_data_t<Is, Types>...> data_;
template<class T>container_t(T const& v) :data_(v) {}
container_t() = default;
container_t(container_t const&) = default;
container_t(container_t&&) = default;
container_t& operator=(container_t const&) = default;
container_t& operator=(container_t&&) = default;
~container_t() = default;
template<class ReturnType, class Funcs>ReturnType function_call(Funcs const& funcs)const
{
return boost::apply_visitor([&](auto const&v) {return v.PLASMA_ADT_TEMPLATE function_call<ReturnType>(funcs);}, data_);
}
template<class ReturnType, class Funcs, class Recursion>ReturnType recursion_call(Funcs const& funcs, Recursion const& recur)const
{
return boost::apply_visitor([&](auto const&v) {return v.PLASMA_ADT_TEMPLATE recursion_call<ReturnType>(funcs, recur);}, data_);
}
template<class ReturnType, class Funcs,class Tuple>ReturnType function_call_with_argument(Funcs const& funcs,Tuple const& arg)const
{
return boost::apply_visitor([&](auto const&v) {return v.PLASMA_ADT_TEMPLATE function_call_with_argument<ReturnType>(funcs, arg, std::make_index_sequence<std::tuple_size<Tuple>::value>());}, data_);
}
template<class ReturnType, class Funcs,class Recursion,class Tuple>ReturnType recursion_call_with_argument(Funcs const& funcs, Recursion const& recur,Tuple const& arg)const
{
return boost::apply_visitor([&](auto const&v) {return v.PLASMA_ADT_TEMPLATE
recursion_call_with_argument<ReturnType>(funcs, recur, arg, std::make_index_sequence<std::tuple_size<Tuple>::value>());}, data_);
}
bool operator==(container_t<std::index_sequence<Is...>> const& rhs)const
{
return data_ == rhs.data_;
}
};
public:
template<std::size_t Id, class T>struct instance_t
{
static this_type run(true_name<T>const& v)
{
instances.emplace_back(inside_data_t<Id, T>(v));
return this_type(std::prev(instances.end()));
}
};
template<std::size_t Id, class... Ts>struct instance_t<Id, std::tuple<Ts...>>
{
static this_type run(true_name<Ts>const&... v)
{
instances.emplace_back(inside_data_t<Id, std::tuple<Ts...>>(v...));
return this_type(std::prev(instances.end()));
}
};
template<std::size_t Id>struct instance_t<Id, void>
{
static this_type run()
{
instances.emplace_back(inside_data_t<Id, void>());
return this_type(std::prev(instances.end()));
}
};
template<std::size_t Id>using instance_type = instance_t<Id, parameter_type<Id>>;
template<std::size_t Id>static auto get_instance_function()
{
return instance_type<Id>::run;
}
data_type(data_type const&) = default;
data_type(data_type&&) = default;
data_type& operator=(data_type const&) = default;
data_type& operator=(data_type&&) = default;
bool operator==(this_type const& rhs)const
{
return *iterator_ == *rhs.iterator_;
}
template<class ReturnType, class Funcs>struct pattern_match_t
{
Funcs funcs;
ReturnType operator()(this_type const& v)const
{
return v.iterator_->PLASMA_ADT_TEMPLATE function_call<ReturnType>(funcs);
}
};
template<class ReturnType, class Funcs>struct recursion_match_t
{
Funcs funcs;
ReturnType operator()(this_type const& v)const
{
return v.iterator_->PLASMA_ADT_TEMPLATE recursion_call<ReturnType>(funcs, std::cref(*this));
}
};
template<class ReturnType, class Tuple, class Funcs>struct pattern_match_with_argument_t;
template<class ReturnType, class Funcs, class... Ts>struct pattern_match_with_argument_t<ReturnType, std::tuple<Ts...>, Funcs>
{
Funcs funcs;
ReturnType operator()(this_type const& v, Ts const&... args)const
{
return v.iterator_->PLASMA_ADT_TEMPLATE function_call_with_argument<ReturnType>(funcs, std::make_tuple(std::cref(args)...));
}
};
template<class ReturnType, class Tuple, class Funcs>struct recursion_match_with_argument_t;
template<class ReturnType, class Funcs, class... Ts>struct recursion_match_with_argument_t<ReturnType, std::tuple<Ts...>, Funcs>
{
Funcs funcs;
ReturnType operator()(this_type const& v, Ts const&... args)const
{
return v.iterator_->PLASMA_ADT_TEMPLATE recursion_call_with_argument<ReturnType>(funcs, std::cref(*this), std::make_tuple(std::cref(args)...));
}
};
template<class ReturnType, class Funcs>struct memoization_pattern_match_t
{
Funcs funcs;
std::shared_ptr<std::vector<std::pair<container, ReturnType>>> data_ptr_;
ReturnType operator()(this_type const& arg)const
{
for (auto const& d : *data_ptr_)
{
if (d.first == *arg.iterator_)
{
return d.second;
}
}
auto ret = arg.iterator_->PLASMA_ADT_TEMPLATE function_call<ReturnType>(funcs);
data_ptr_->emplace_back(*arg.iterator_, ret);
return ret;
}
};
template<class ReturnType, class Funcs>struct memoization_recursion_match_t
{
Funcs funcs;
std::shared_ptr<std::vector<std::pair<container, ReturnType>>> data_ptr_;
ReturnType operator()(this_type const& arg)const
{
for (auto const& d : *data_ptr_)
{
if (d.first == *arg.iterator_)
{
return d.second;
}
}
auto ret = arg.iterator_->PLASMA_ADT_TEMPLATE recursion_call<ReturnType>(funcs, std::cref(*this));
data_ptr_->emplace_back(*arg.iterator_, ret);
return ret;
}
};
template<class ReturnType, class Tuple>struct make_shared_t;
template<class ReturnType, class... Ts>struct make_shared_t<ReturnType, std::tuple<Ts...>>
{
static auto run()
{
return std::make_shared<std::vector<std::pair<std::tuple<container, Ts...>, ReturnType>>>();
}
};
template<class ReturnType, class Tuple, class Funcs>struct memoization_pattern_match_with_argument_t;
template<class ReturnType, class Funcs, class... Ts>struct memoization_pattern_match_with_argument_t<ReturnType, std::tuple<Ts...>, Funcs>
{
Funcs funcs;
std::shared_ptr<std::vector<std::pair<std::tuple<container, Ts...>, ReturnType>>> data_ptr_;
ReturnType operator()(this_type const& v, Ts const&... args)const
{
auto t = std::make_tuple(*v.iterator_, args...);
for (auto const& d : *data_ptr_)
{
if (t == d.first)
{
return d.second;
}
}
auto ret = v.iterator_->PLASMA_ADT_TEMPLATE function_call_with_argument<ReturnType>(funcs, std::make_tuple(std::cref(args)...));
data_ptr_->emplace_back(t, ret);
return ret;
}
};
template<class ReturnType, class Tuple, class Funcs>struct memoization_recursion_match_with_argument_t;
template<class ReturnType, class Funcs, class... Ts>struct memoization_recursion_match_with_argument_t<ReturnType, std::tuple<Ts...>, Funcs>
{
Funcs funcs;
std::shared_ptr<std::vector<std::pair<std::tuple<container, Ts...>, ReturnType>>> data_ptr_;
ReturnType operator()(this_type const& v, Ts const&... args)const
{
auto t = std::make_tuple(*v.iterator_, args...);
for (auto const& d : *data_ptr_)
{
if (t == d.first)
{
return d.second;
}
}
auto ret = v.iterator_->PLASMA_ADT_TEMPLATE recursion_call_with_argument<ReturnType>(funcs, std::cref(*this), std::make_tuple(std::cref(args)...));
data_ptr_->emplace_back(t, ret);
return ret;
}
};
private:
template<class ReturnType, class FunctionFlag, class ArgumentTuple, class Funcs>
static auto make_function(Funcs const& funcs, std::enable_if_t<FunctionFlag::flag == 0b00>* = nullptr)
{
return pattern_match_t<ReturnType, Funcs>{funcs};
}
template<class ReturnType, class FunctionFlag, class ArgumentTuple, class Funcs>
static auto make_function(Funcs const& funcs, std::enable_if_t<FunctionFlag::flag == 0b01>* = nullptr)
{
return recursion_match_t<ReturnType, Funcs>{funcs};
}
template<class ReturnType, class FunctionFlag, class ArgumentTuple, class Funcs>
static auto make_function(Funcs const& funcs, std::enable_if_t<FunctionFlag::flag == 0b10>* = nullptr)
{
return memoization_pattern_match_t<ReturnType, Funcs>{funcs, std::make_shared<std::vector<std::pair<container, ReturnType>>>()};
}
template<class ReturnType, class FunctionFlag, class ArgumentTuple, class Funcs>
static auto make_function(Funcs const& funcs, std::enable_if_t<FunctionFlag::flag == 0b11>* = nullptr)
{
return memoization_recursion_match_t<ReturnType, Funcs>{funcs, std::make_shared<std::vector<std::pair<container, ReturnType>>>()};
}
template<class ReturnType, class FunctionFlag, class ArgumentTuple, class Funcs>
static auto make_function_with(Funcs const& funcs, std::enable_if_t<FunctionFlag::flag == 0b00>* = nullptr)
{
return pattern_match_with_argument_t<ReturnType, ArgumentTuple, Funcs>{funcs};
}
template<class ReturnType, class FunctionFlag, class ArgumentTuple, class Funcs>
static auto make_function_with(Funcs const& funcs, std::enable_if_t<FunctionFlag::flag == 0b01>* = nullptr)
{
return recursion_match_with_argument_t<ReturnType, ArgumentTuple, Funcs>{funcs};
}
template<class ReturnType, class FunctionFlag, class ArgumentTuple, class Funcs>
static auto make_function_with(Funcs const& funcs, std::enable_if_t<FunctionFlag::flag == 0b10>* = nullptr)
{
return memoization_pattern_match_with_argument_t<ReturnType, ArgumentTuple, Funcs>{funcs, make_shared_t<ReturnType, ArgumentTuple>::run()};
}
template<class ReturnType, class FunctionFlag, class ArgumentTuple, class Funcs>
static auto make_function_with(Funcs const& funcs, std::enable_if_t<FunctionFlag::flag == 0b11>* = nullptr)
{
return memoization_recursion_match_with_argument_t<ReturnType, ArgumentTuple, Funcs>{funcs, make_shared_t<ReturnType, ArgumentTuple>::run()};
}
public:
template<class ReturnType, class ArgumentTuple, class FunctionFlag, class... Funcs>static auto make_pattern_match(FunctionFlag const&, Funcs const&... funcs)
->typename std::enable_if<
function_flag::is_function_flag<FunctionFlag>::value&&function_flag::is_tuple<ArgumentTuple>::value
, decltype(make_function_with<ReturnType, FunctionFlag, ArgumentTuple>(std::make_tuple(funcs...)))>::type
{
return make_function_with<ReturnType, FunctionFlag, ArgumentTuple>(std::make_tuple(funcs...));
}
template<class ReturnType, class ArgumentTuple,class F, class... Funcs>static auto make_pattern_match(F const& func, Funcs const&... funcs)
->typename std::enable_if<
function_flag::is_tuple<ArgumentTuple>::value && !function_flag::is_function_flag<F>::value
, decltype(make_function_with<ReturnType, function_flag::function_flag_t<0b00>, ArgumentTuple>(std::make_tuple(func, funcs...)))>::type
{
return make_function_with<ReturnType, function_flag::function_flag_t<0b00>, ArgumentTuple>(std::make_tuple(func, funcs...));
}
template<class ReturnType, class FunctionFlag, class... Funcs>static auto make_pattern_match(FunctionFlag const&, Funcs const&... funcs)
->typename std::enable_if<
function_flag::is_function_flag<FunctionFlag>::value
, decltype(make_function<ReturnType, FunctionFlag, std::tuple<void>>(std::make_tuple(funcs...)))>::type
{
return make_function<ReturnType, FunctionFlag, std::tuple<void>>(std::make_tuple(funcs...));
}
template<class ReturnType,class F, class... Funcs>static auto make_pattern_match(F const& func, Funcs const&... funcs)
->typename std::enable_if<
!function_flag::is_function_flag<F>::value
,decltype(make_function<ReturnType, function_flag::function_flag_t<0b00>, std::tuple<void>>(std::make_tuple(func, funcs...)))>::type
{
return make_function<ReturnType, function_flag::function_flag_t<0b00>, std::tuple<void>>(std::make_tuple(func, funcs...));
}
};
template<class... Types>typename data_type<Types...>::list_type data_type<Types...>::instances;
}
#include"adt_rebirth.hpp"
#include<iostream>
using namespace plasma_adt;
using namespace function_flag;
typedef data_type<std::tuple<int>, std::tuple<double>> type;
const auto Int = type::get_instance_function<0>();
const auto Double = type::get_instance_function<1>();
const auto get = type::make_pattern_match<double>(
[](int x)
{
return static_cast<double>(x);
},
[](double y)
{
return y;
});
const auto sum = type::make_pattern_match<double, std::tuple<double>>(
[](int x, double d)
{
return x + d;
}, [](double x, double y) { return x + y; });
int main()
{
auto i = Int(10);
auto d = Double(20.0);
std::cout << get(i) << std::endl;
std::cout << sum(d,2.0) << std::endl;
}
#include"adt_rebirth.hpp"
#include<iostream>
using namespace plasma_adt;
using namespace function_flag;
typedef data_type<void, std::tuple<int, recursion_tag>> list;
const auto Nil = list::get_instance_function<0>();
const auto Tree = list::get_instance_function<1>();
const auto sum = list::make_pattern_match<int>(recursion_flag,
[](auto)
{
return 0;
},
[](auto f, int v, list next)
{
return v + f(next);
});
const auto sum2 = list::make_pattern_match<int, std::tuple<int>>(recursion_flag,
[](auto, int x)
{
return x;
},
[](auto f, int v, list next, int n)
{
return v + f(next, n);
});
int main()
{
auto t = Tree(1, Tree(2, Tree(3, Nil())));
std::cout << sum(t) << std::endl;
std::cout << sum2(t,2) << std::endl;
}

##これなに 再誕してとても早くなったのだ

##それはどうでもいい C++でも代数的データ型を使いたい人のためのライブラリです。

##動作環境 msvcとgccとclangで動作を確認しております。
内部でboostを使っていますのでboostにパスを通しておいてください。

##俺のVisual Studioで使えない VS2015にしてくれ頼む

##使い方 ###STEP1 代数データ型を定義しよう data_typeに好きな型をぶっこんで代数データ型を作ります。
このようにしてぶっこんだ順番を覚えておきます。 ####選べる3タイプ ・void
要素がないです。
・非void単体
一つだけです。
・std::tuple
複数の要素を持てます。
####data_type型の要素を入れたい 単体かstd::tupleにplasma_adt::recursion_tagを入れればそこがdata_typeになります。 ###STEP2 インスタンス関数を生成しよう staticメンバ関数get_instance_functionのテンプレート引数にインスタンス関数を作りたい番号を放り込んで呼びます。
const autoで受けていい感じの名前をつけるとよいでしょう。 ###STEP3 パターンマッチする関数を定義しよう 代数データ型なのでパターンマッチ(の弱い版みたいなの)をしましょう、そのために関数オブジェクトを定義します。
make_pattern_match<ReturnType>で返り値の型がReturnTypeの関数を定義できます。 ####より便利にパターンマッチする make_pattern_match<ReturnType, std::tuple<Ts...>>で引数Ts...を右に付け加えることができます。
また第1引数にfunction_flag名前空間内のオプション定数を渡すことで関数をより変化させることができます。 #####function_flagの内訳 ・no_option_flag
渡さないのと同等です。
・recursion_flag
再帰が可能となります。make_pattern_matchの引数の各関数オブジェクトの第1引数に再帰用の関数が渡されます。
・memoization_flag
メモ化する関数になります。
・dual_flag
上2つを同時に適用します。
ちなみにこれらはoperator+で結合できます。

##注意 内部でstatic変数を使ってるので環境にもよりますがグローバル変数(定数含む)で直接インスタンス化しようとするとセグフォったりします。
またVS2015を使っている場合dual_flagを渡すと何故かインテリセンスがエラー判定を返すようになります。コンパイルは通ります。

##Special Thanks @_primenumber 「make_pattern_matchに引数を渡すことでスイッチする」ことでクソみたいに長い関数名を短くする案をくれた

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment