#include #include #include using namespace origin; using namespace eop; using std::cout; int root(int x) { return 0; } bool root2(int x, int y) { return 0; } bool root3(int x, char c, long z) { return false; } struct root_func : std::unary_function { int operator()(bool) const { return 1; } }; struct root2_func : std::binary_function { int operator()(char, bool) const { return 1; } }; // NOTE: All functional concepts are adapted to function pointers, not function // types. This is to say that we specialize on Result(*)(Args...) rather than // Result(Args...). The reason for this is that a template accepting a function // parameter is parameterized by a function pointer. The type of the function // pointer can be accessed as decltype(*f), generating the non-pointer // signature. template void test(F f) { cout << "--- " << typestr() << " ---\n"; cout << " * arguments: " << typestr::type>() << "\n"; cout << " * result: " << typestr::type>() << "\n"; cout << "Procedure? " << Procedure::check::value << "\n"; cout << "RegularProcedure? " << RegularProcedure::check::value << "\n"; cout << "FunctionalProcedure? " << FunctionalProcedure::check::value << "\n"; cout << "UnaryFunction? " << UnaryFunction::check::value << "\n"; cout << "BinaryFunction? " << BinaryFunction::check::value << "\n"; cout << "HomogenousFunction? " << HomogenousFunction::check::value << "\n"; cout << "Predicate? " << eop::Predicate::check::value << "\n"; cout << "UnaryPredicate? " << UnaryPredicate::check::value << "\n"; cout << "BinaryPredicate? " << BinaryPredicate::check::value << "\n"; cout << "HomogenousPredicate? " << HomogenousPredicate::check::value << "\n"; cout << "Operation? " << Operation::check::value << "\n"; cout << "\n"; } int main() { test(root); test(root2); test(root_func()); test(root2_func()); // TODO: Fix ostream? // cout << origin::Regular::check::value << "\n"; // TODO: Fix regular so that we can check it with void types/ // cout << origin::Regular::check::value << "\n"; return 0; }