#include <type_traits>
#include <tuple>
namespace mplex {
template <std::size_t N> struct placeholder {
static constexpr std::size_t value = N;
template <typename T>
friend auto constexpr eval(placeholder, T&& tuple) { return std::get<N>(std::forward<T>(tuple)); }
};
using p1 = placeholder<0>;
using p2 = placeholder<1>;
using p3 = placeholder<2>;
template <typename T> struct expression_template { using type = T; };
auto _1 = expression_template<p1>{};
auto _2 = expression_template<p2>{};
auto _3 = expression_template<p3>{};
template <int Value>
expression_template<std::integral_constant<int, Value> > int_();
template <typename T, T Value, typename X>
auto constexpr eval(std::integral_constant<T, Value>, X&&) { return Value; }
template <typename L, typename R>
struct mul {
template <typename T>
friend auto constexpr eval(mul, T&& tuple) { return eval(L{}, tuple)*eval(R{}, tuple); }
};
template <typename A, typename B>
auto operator*(expression_template<A>, expression_template<B>) -> expression_template<mul<A, B>>;
template <typename L, typename R>
struct add {
template <typename T>
friend auto constexpr eval(add, T&& tuple) { return eval(L{}, tuple)+eval(R{}, tuple); }
};
template <typename A, typename B>
auto operator+(expression_template<A>, expression_template<B>) -> expression_template<add<A, B>>;
template <typename L, typename R>
struct div {
template <typename T>
friend constexpr auto eval(div, T&& tuple) { return eval(L{}, tuple)/eval(R{}, tuple); }
};
template <typename A, typename B>
auto operator/(expression_template<A>, expression_template<B>) -> expression_template<div<A, B>>;
} // namespace mplex
int main()
{
using namespace mplex;
using newFunctor = decltype((_1 + int_<7>())*(_2/_3))::type;
auto constexpr result = eval(newFunctor{}, std::make_tuple(1, 6, 3));
static_assert(result == (1+7)*(6/3), "");
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8dHVwbGU+CgpuYW1lc3BhY2UgbXBsZXggewoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IE4+IHN0cnVjdCBwbGFjZWhvbGRlciB7CiAgc3RhdGljIGNvbnN0ZXhwciBzdGQ6OnNpemVfdCB2YWx1ZSA9IE47CgogIHRlbXBsYXRlIDx0eXBlbmFtZSBUPgogIGZyaWVuZCBhdXRvIGNvbnN0ZXhwciBldmFsKHBsYWNlaG9sZGVyLCBUJiYgdHVwbGUpIHsgcmV0dXJuIHN0ZDo6Z2V0PE4+KHN0ZDo6Zm9yd2FyZDxUPih0dXBsZSkpOyB9Cn07CnVzaW5nIHAxID0gcGxhY2Vob2xkZXI8MD47CnVzaW5nIHAyID0gcGxhY2Vob2xkZXI8MT47CnVzaW5nIHAzID0gcGxhY2Vob2xkZXI8Mj47Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4gc3RydWN0IGV4cHJlc3Npb25fdGVtcGxhdGUgeyB1c2luZyB0eXBlID0gVDsgfTsKCmF1dG8gXzEgPSBleHByZXNzaW9uX3RlbXBsYXRlPHAxPnt9OwphdXRvIF8yID0gZXhwcmVzc2lvbl90ZW1wbGF0ZTxwMj57fTsKYXV0byBfMyA9IGV4cHJlc3Npb25fdGVtcGxhdGU8cDM+e307Cgp0ZW1wbGF0ZSA8aW50IFZhbHVlPgpleHByZXNzaW9uX3RlbXBsYXRlPHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8aW50LCBWYWx1ZT4gPiBpbnRfKCk7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgVCBWYWx1ZSwgdHlwZW5hbWUgWD4KYXV0byBjb25zdGV4cHIgZXZhbChzdGQ6OmludGVncmFsX2NvbnN0YW50PFQsIFZhbHVlPiwgWCYmKSB7IHJldHVybiBWYWx1ZTsgfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEwsIHR5cGVuYW1lIFI+CnN0cnVjdCBtdWwgewogIHRlbXBsYXRlIDx0eXBlbmFtZSBUPgogIGZyaWVuZCBhdXRvIGNvbnN0ZXhwciBldmFsKG11bCwgVCYmIHR1cGxlKSB7IHJldHVybiBldmFsKEx7fSwgdHVwbGUpKmV2YWwoUnt9LCB0dXBsZSk7IH0KfTsKdGVtcGxhdGUgPHR5cGVuYW1lIEEsIHR5cGVuYW1lIEI+CmF1dG8gb3BlcmF0b3IqKGV4cHJlc3Npb25fdGVtcGxhdGU8QT4sIGV4cHJlc3Npb25fdGVtcGxhdGU8Qj4pIC0+IGV4cHJlc3Npb25fdGVtcGxhdGU8bXVsPEEsIEI+PjsKCnRlbXBsYXRlIDx0eXBlbmFtZSBMLCB0eXBlbmFtZSBSPgpzdHJ1Y3QgYWRkIHsKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KICBmcmllbmQgYXV0byBjb25zdGV4cHIgZXZhbChhZGQsIFQmJiB0dXBsZSkgeyByZXR1cm4gZXZhbChMe30sIHR1cGxlKStldmFsKFJ7fSwgdHVwbGUpOyB9Cn07CnRlbXBsYXRlIDx0eXBlbmFtZSBBLCB0eXBlbmFtZSBCPgphdXRvIG9wZXJhdG9yKyhleHByZXNzaW9uX3RlbXBsYXRlPEE+LCBleHByZXNzaW9uX3RlbXBsYXRlPEI+KSAtPiBleHByZXNzaW9uX3RlbXBsYXRlPGFkZDxBLCBCPj47Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgTCwgdHlwZW5hbWUgUj4Kc3RydWN0IGRpdiB7CiAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CiAgZnJpZW5kIGNvbnN0ZXhwciBhdXRvIGV2YWwoZGl2LCBUJiYgdHVwbGUpIHsgcmV0dXJuIGV2YWwoTHt9LCB0dXBsZSkvZXZhbChSe30sIHR1cGxlKTsgfQp9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgQSwgdHlwZW5hbWUgQj4KYXV0byBvcGVyYXRvci8oZXhwcmVzc2lvbl90ZW1wbGF0ZTxBPiwgZXhwcmVzc2lvbl90ZW1wbGF0ZTxCPikgLT4gZXhwcmVzc2lvbl90ZW1wbGF0ZTxkaXY8QSwgQj4+OwoKfSAvLyBuYW1lc3BhY2UgbXBsZXgKCmludCBtYWluKCkKewogIHVzaW5nIG5hbWVzcGFjZSBtcGxleDsKICB1c2luZyBuZXdGdW5jdG9yID0gZGVjbHR5cGUoKF8xICsgaW50Xzw3PigpKSooXzIvXzMpKTo6dHlwZTsKICBhdXRvIGNvbnN0ZXhwciByZXN1bHQgPSBldmFsKG5ld0Z1bmN0b3J7fSwgc3RkOjptYWtlX3R1cGxlKDEsIDYsIDMpKTsKICBzdGF0aWNfYXNzZXJ0KHJlc3VsdCA9PSAoMSs3KSooNi8zKSwgIiIpOwp9Cg==