template <class Derived>
class base
{
public:
virtual ~base() = default;
auto operator()()
const noexcept { return dynamic_cast<const Derived&>(*this)(); }
};
class derived : public base<derived>
{
public:
auto operator()()
const noexcept { return 0; }
};
template <class A, class B>
class expr : public base<expr<A, B>>
{
const A m_a;
const B m_b;
public:
explicit expr(const A a, const B b)
noexcept : m_a(a), m_b(b) {}
auto operator()()
const noexcept { return m_a() + m_b(); }
};
template <class D1, class D2>
auto foo(const base<D1>& d1, const base<D2>& d2)
noexcept { return expr<base<D1>, base<D2>>{d1, d2}; }
int main()
{
auto d = derived{};
auto e = foo(d, d);
return e();
}
dGVtcGxhdGUgPGNsYXNzIERlcml2ZWQ+CmNsYXNzIGJhc2UKewpwdWJsaWM6CiAgICB2aXJ0dWFsIH5iYXNlKCkgPSBkZWZhdWx0OwogICAgYXV0byBvcGVyYXRvcigpKCkKICAgIGNvbnN0IG5vZXhjZXB0IHsgcmV0dXJuIGR5bmFtaWNfY2FzdDxjb25zdCBEZXJpdmVkJj4oKnRoaXMpKCk7IH0KfTsKCmNsYXNzIGRlcml2ZWQgOiBwdWJsaWMgYmFzZTxkZXJpdmVkPgp7CnB1YmxpYzoKICAgIGF1dG8gb3BlcmF0b3IoKSgpCiAgICBjb25zdCBub2V4Y2VwdCB7IHJldHVybiAwOyB9Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgQSwgY2xhc3MgQj4KY2xhc3MgZXhwciA6IHB1YmxpYyBiYXNlPGV4cHI8QSwgQj4+CnsKICAgIGNvbnN0IEEgbV9hOwogICAgY29uc3QgQiBtX2I7CnB1YmxpYzoKICAgIGV4cGxpY2l0IGV4cHIoY29uc3QgQSBhLCBjb25zdCBCIGIpCiAgICBub2V4Y2VwdCA6IG1fYShhKSwgbV9iKGIpIHt9CgogICAgYXV0byBvcGVyYXRvcigpKCkKICAgIGNvbnN0IG5vZXhjZXB0IHsgcmV0dXJuIG1fYSgpICsgbV9iKCk7IH0KfTsKCnRlbXBsYXRlIDxjbGFzcyBEMSwgY2xhc3MgRDI+CmF1dG8gZm9vKGNvbnN0IGJhc2U8RDE+JiBkMSwgY29uc3QgYmFzZTxEMj4mIGQyKQpub2V4Y2VwdCB7IHJldHVybiBleHByPGJhc2U8RDE+LCBiYXNlPEQyPj57ZDEsIGQyfTsgfQoKaW50IG1haW4oKQp7CiAgICBhdXRvIGQgPSBkZXJpdmVke307CiAgICBhdXRvIGUgPSBmb28oZCwgZCk7CiAgICByZXR1cm4gZSgpOwp9Cg==