0

I would like to return a std::future from a class method. The value type of the std::future depends on the concrete class. I wonder how I can get() the value of the std::future without knowing a priori which concrete class is used.

Here's a simplified example, which uses only one derived ValueA and AppA class. In my real world problem, I have multiple classes (AppB with ValueB etc) inheriting from the corresponding base classes. I would like to avoid using a templated App class, as in the real world most methods do not depend on the type of ValueBase.

#include <future>
#include <memory>

class ValueBase
{
public:
  virtual int value() const = 0;
};

class ValueA : public ValueBase
{
public:
  int value() const override
  {
    return 0;
  }
};


class AppBase
{
public:
  virtual std::future<const ValueBase&> get() = 0;
};

class AppA : public AppBase
{
public:
  std::future<const ValueBase&> get() override
  {
    std::promise<const ValueBase&> promise;
    promise.set_value(value_);
    return promise.get_future();
  }

private:
  ValueA value_;
};


int main()
{
  std::unique_ptr<AppBase> app = std::make_unique<AppA>();
  auto future = app->get();

  // If I know that app uses ValueA, I can cast it
  const auto valueA = dynamic_cast<const ValueA&>(future.get());

  // How to get the value if the type/concrete class is not known?
  // The following line does not compile with
  // Variable type 'const ValueBase' is an abstract class
  const auto value = future.get();
}
  • 1
    Your problem is not related to `std::future` which is obfuscating the question. Any function that returns a reference to the base type will experience the same issue. The real answer is, perhaps unhelpfully, that you shouldn't design your program in such a way that you care about the actual concrete type returned. Perhaps you need compile-time polymorphism using templates instead of runtime polymorphism using `virtual`. – François Andrieux Jul 23 '21 at 13:39
  • Why not use `future.get()` as `const ValueBase&` (so calling `value()` (which should be `const`) from it). – Jarod42 Jul 23 '21 at 13:44
  • It isn't clear what error or problem exactly you are trying to overcome, but `const auto value = future.get();` causes [object slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing) which may be the cause of your error. Use `const auto & value` instead. Otherwise, you are copying the `ValueBase` part of your the returned object. Using a reference avoids this copy. Consider `= delete`ing the copy constructor and copy assignment operator from your base class. – François Andrieux Jul 23 '21 at 13:54

0 Answers0