Skip to content

Instantly share code, notes, and snippets.

@Fuyutsubaki
Created August 5, 2013 15:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Fuyutsubaki/6156874 to your computer and use it in GitHub Desktop.
Save Fuyutsubaki/6156874 to your computer and use it in GitHub Desktop.
prologの事実みたいなことをC++でもしたい
#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