You can actually have your MonteCarlo::inference
return a pointer (or reference) to a MonteCarlo::InferenceData
, as long as you do things correctly otherwise. A simple version looks like this:
#include <memory>
#include <iostream>
template <typename StateType>
class Model {
public:
// base return type:
struct InferenceData { };
virtual InferenceData *inference() = 0;
};
template <typename StateType>
class MonteCarlo : public Model<StateType> {
public:
// derived return type must be derived from base return type:
struct InferenceData : public ::Model<StateType>::InferenceData { };
InferenceData *inference() { return new InferenceData; }
};
int main() {
MonteCarlo<int> mci;
auto v = mci.inference();
}
This a a covariant return type (as the compiler alluded to in its error message). There are a couple of points to keep in mind here though:
- The return type really does have to be covariant. That is, the base class function has to be declared to return a pointer/reference to some base class, and the derived function has to return a pointer/reference to a type derived from that that the base function returns.
- A
unique_ptr<Derived>
allows implicit conversion to unique_ptr<Base>
, assuming Derived
is derived from Base
, but a unique_ptr<Derived>
still isn't actually derived from unique_ptr<Base>
, so you can't use (most typical) smart pointers for covariant returns.
For the moment, I've used new
to create the returned object. That's pretty common when dealing with derivation and such, but it can be avoided if necessary. Doing that can get non-trivial in itself, depending on your needs. In a really simple case, define a static object of the correct type, and return a pointer to it (but that leads to problems if you do multi-threading).