Edit: My question might just be asking how to downcast a unique_ptr<base> to unique_ptr<derived> (which is already answered), but I am not 100% sure what I am asking
I have an Abstract Base Class Base
class Base{
  public:
    Base();
    struct pStruct{};
    virtual pStruct pFunc(std::vector<double> data) = 0;
  protected:
    CustomType dataValue;
};
and two derived classes Derived1 and Derived2 that implement Base
class Derived1 : public Base {
  public:
    struct pStructD1 : Base::pStruct {
      CustomType data1;
      std::vector<double> data2;
    };
    Derived1(uint32_t foo1, std::vector<double> foo2, ...);
    virtual pStruct pFunc(std::vector<double> data) override;
  private:
    uint32_t bar1{0};
};
class Derived2 : public Base {
  public:
    struct pStructD2 : Base::pStruct {
      int32_t data3;
      std::vector<double> data4;
      double data5
    };
    Derived2(std::vector<double> foo1, std::vector<double> foo2, ...);
    virtual pStruct pFunc(std::vector<double> data) override;
  private:
    std::vector<double> bar2;
};
When calling class method pFunc(std::vector<double> data), each derived class will return different types, and amounts of values. I tried making this work with a covariant return type, so Derived1::predict(data).key1 might be a matrix, and .key2 might be something else, and so on. Derived2::predict(data).key1 might be the only key, and it could be a boolean. Each derived class defines their own ::predict() return fields, because they vary significantly.
The issue is, I construct these derived classes with a factory, that reads some of the input (construction is via ifstream), and figures out what derived class it should be, and then calls the corresponding factory.
class BaseFactory {
  public:
    static std::unique_ptr<Base> createObj(std::ifstream & file){
      file.read((char *) specificTypeString, 2);//This isn't actually the code, just assume this part works
      if(specificTypeString == "D2"){
        return D2BaseFactory::createObj(file);
      }
      else if(specificTypeString == "D1"){
        return D1BaseFactory::createObj(file);
      }
      else{
        throw std::runtime_error("error");
      }
    }
};
With std::unique_ptr<Base> D1BaseFactory::createObj(std::ifstream & file); returning std::unique_ptr<Derived1>(new Derived1(param1, param2, ...)); and the same thing for `D2BaseFactory'.
Problem is, if I construct a Derived class with the common BaseFactory, and call pFunc() on the returned unique_ptr, it always will be the empty Base::pStruct == {} and thus trying to access members of the covariant pStructs isn't possible. I know this is because the factory createObj returns the base type, but is there any way to dynamically return the type I want so I can access the necessary fields in the derived pStructs? I think using raw pointers might work, but if possible i'd like to keep them as unique pointers.
 
    