Created
August 5, 2013 15:34
-
-
Save Fuyutsubaki/6156874 to your computer and use it in GitHub Desktop.
prologの事実みたいなことをC++でもしたい
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<tuple> | |
#include<vector> | |
namespace proloog | |
{ | |
class None{}; | |
class Var{}; | |
template<class... X> | |
class Fact | |
{ | |
public: | |
typedef std::tuple<X...> Tuple; | |
typedef std::vector<Tuple>result_type; | |
void set(const X & ... x) | |
{ | |
data.push_back(Tuple(x...)); | |
} | |
static const size_t ELEM_SIZE = sizeof...(X); | |
result_type operator()(const boost::variant<Var, None, X>& ... x) | |
{ | |
UniqueChecker uniquer(x...); | |
result_type result; | |
bool r = false; | |
for (auto&t : data) | |
{ | |
if (isMatch(t,x...)) | |
{ | |
//何も一致しない | |
if (!std::any_of(result.begin(), result.end(), [&](const Tuple&lhs){return uniquer(lhs, t); })) | |
{ | |
result.push_back(t); | |
} | |
} | |
} | |
return result; | |
} | |
private: | |
std::vector<Tuple> data; | |
//検出 | |
template<class T> | |
struct CheckVisitor : public boost::static_visitor<bool> | |
{ | |
CheckVisitor(const T&x) | |
: x(x){} | |
bool operator()(const T&rhs)const | |
{ | |
return x == rhs; | |
} | |
bool operator()(const Var&) const{ return true; } | |
bool operator()(const None&) const{ return true; } | |
private: | |
const T&x; | |
}; | |
bool isMatch(const Tuple&)const | |
{ | |
return true; | |
} | |
template <class First, class ...Rest> | |
bool isMatch(const Tuple&tuple, First first, Rest ...rest)const | |
{ | |
static const size_t N = ELEM_SIZE - (sizeof...(Rest) + 1); | |
typedef std::tuple_element<N, Tuple>::type T; | |
return | |
boost::apply_visitor(CheckVisitor<T>(std::get<N>(tuple)), first) | |
&& isMatch(tuple,rest...); | |
} | |
class UniqueChecker | |
{ | |
public: | |
UniqueChecker(const boost::variant<Var, None, X>& ... x) | |
{ | |
build(x...); | |
} | |
bool operator()(const Tuple&lhs, const Tuple&rhs)const | |
{ | |
return std::all_of(data.begin(), data.end(), | |
[&](const Func&f){return f(lhs, rhs); } | |
); | |
} | |
private: | |
typedef std::function<bool (const Tuple&lhs, const Tuple&rhs)> Func; | |
std::vector<Func> data; | |
void build(){} | |
template <class First, class ...Rest> | |
void build(const First&first,const Rest&...rest) | |
{ | |
static const size_t N = ELEM_SIZE - (sizeof...(Rest) + 1); | |
typedef std::tuple_element<N, Tuple>::type T; | |
if (boost::apply_visitor(Checker<T>(),first)) | |
{ | |
data.push_back([](const Tuple&lhs, const Tuple&rhs) | |
{ | |
return std::get<N>(lhs) == std::get<N>(rhs); | |
}); | |
} | |
build(rest...); | |
} | |
template<class T> | |
struct Checker : public boost::static_visitor<bool> | |
{ | |
bool operator()(const T&)const{return false;} | |
bool operator()(const Var&) const{ return true; } | |
bool operator()(const None&) const{ return false; } | |
}; | |
}; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment