Last active
February 24, 2018 07:00
-
-
Save 2bbb/3c91f7e57fe4371618b9db39144582ec to your computer and use it in GitHub Desktop.
infix_op
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
#include <utility> | |
namespace bbb { | |
namespace infix_op { | |
template <typename function_type> | |
struct infix_op { | |
inline infix_op() : f() {}; | |
template <typename ... arguments> | |
inline infix_op(arguments ... args) : f(std::forward<arguments>(args) ...) {}; | |
template <typename left_arg, typename right_arg> | |
using result_type = decltype(std::declval<function_type>()(std::declval<left_arg>(), std::declval<right_arg>())); | |
template <typename left_arg> | |
struct partial_applied { | |
partial_applied(function_type f, left_arg &lhs) : f(std::move(f)), lhs(lhs) {}; | |
template <typename right_arg> | |
result_type<left_arg, right_arg> operator|(right_arg &&rhs) | |
{ return f(lhs, std::forward<right_arg>(rhs)); } | |
template <typename right_arg> | |
result_type<left_arg, right_arg> operator|=(right_arg &&rhs) | |
{ return lhs = f(lhs, std::forward<right_arg>(rhs)); } | |
private: | |
function_type f; | |
left_arg &lhs; | |
}; | |
template <typename left_arg> | |
struct partial_applied<const left_arg> { | |
partial_applied(function_type f, const left_arg &lhs) : f(std::move(f)), lhs(lhs) {}; | |
partial_applied(function_type f, left_arg &&lhs) : f(std::move(f)), lhs(std::move(lhs)) {}; | |
template <typename right_arg> | |
result_type<left_arg, right_arg> operator|(right_arg &&rhs) & | |
{ return f(lhs, std::forward<right_arg>(rhs)); } | |
template <typename right_arg> | |
result_type<left_arg, right_arg> operator|(right_arg &&rhs) && | |
{ return f(std::move(lhs), std::forward<right_arg>(rhs)); } | |
private: | |
function_type f; | |
left_arg lhs; | |
}; | |
template <typename left_arg> | |
friend partial_applied<const left_arg> operator|(left_arg &&lhs, const infix_op &op) | |
{ return {op.f, std::forward<left_arg>(lhs)}; } | |
template <typename left_arg> | |
friend partial_applied<left_arg> operator|(left_arg &lhs, const infix_op &op) | |
{ return {op.f, lhs}; } | |
private: | |
function_type f; | |
}; | |
template <typename function_type> | |
infix_op<function_type> make_op(function_type f) { return {f}; }; | |
template <typename function_type, typename ... arguments> | |
infix_op<function_type> make_op(arguments && ... args) { return {std::forward<arguments>(args) ...}; }; | |
}; | |
}; | |
#pragma mark example | |
#include <string> | |
#include <sstream> | |
#include <iostream> | |
using namespace bbb::infix_op; | |
namespace op_def { | |
static int add(int x, int y) { | |
return x + y; | |
} | |
struct add_t { | |
inline int operator()(int x, int y) { return x + y; }; | |
inline int operator()(float x, float y) { return x + y; }; | |
template <typename lhs, typename rhs> | |
inline std::string operator()(lhs l, rhs r) { | |
return (std::stringstream("") << l << r).str(); | |
} | |
}; | |
}; | |
const infix_op<decltype(&op_def::add)> op1{&op_def::add}; | |
const decltype(make_op(op_def::add)) op2{make_op(op_def::add)}; | |
const decltype(make_op(op_def::add_t())) op3{make_op(op_def::add_t())}; | |
const infix_op<op_def::add_t> op4; | |
int main(int argc, char *argv[]) { | |
const auto p = make_op<op_def::add_t>(); | |
auto c = 1 |p| 2 |p| 3; | |
auto d = 1 |p| 2 |p| "3"; | |
auto e = operator|(1.5f, p); // 1.5f | p | |
auto f = e.operator|(3.5f); // e | 3.5f | |
std::cout << c << std::endl; | |
std::cout << d << std::endl; | |
std::cout << f << std::endl; | |
int n = 4; | |
n |p|= 4; | |
std::cout << n << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment