Skip to content

Instantly share code, notes, and snippets.

@2bbb
Last active February 24, 2018 07:00
Show Gist options
  • Save 2bbb/3c91f7e57fe4371618b9db39144582ec to your computer and use it in GitHub Desktop.
Save 2bbb/3c91f7e57fe4371618b9db39144582ec to your computer and use it in GitHub Desktop.
infix_op
#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