#include <future>
#include <memory>
#include <iostream>

class IWidget {
public:
  virtual ~IWidget(){}
  virtual std::future<double> calculateSomethingAsync() const = 0;
};

class Widget : public std::enable_shared_from_this<Widget>, public IWidget {
  double data;
  
  double calculateSomethingInternal() const;
protected:
  Widget(double init) : data(init) {}  // protected, use create
public:
  std::future<double> calculateSomethingAsync() const override;
  
  static std::shared_ptr<IWidget> create(double init);
};

std::shared_ptr<IWidget>
Widget::create(double init) {
  return std::shared_ptr<IWidget>(new Widget(init));
}

double
Widget::calculateSomethingInternal() const {
  return (data + 5.0) / 2.0;
}

std::future<double>
Widget::calculateSomethingAsync() const {
  auto shared_this = shared_from_this();
  return std::async([shared_this]{ return shared_this->calculateSomethingInternal(); });
}

int main() {
    std::future<double> result_task;
    {
      std::shared_ptr<IWidget> w = Widget::create(42.0);  
      result_task = w->calculateSomethingAsync();
    }  // w shared_ptr goes out-of-scope here.
    auto result = result_task.get();
    std::cout << result << "\n";
}