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();
}
