How do I properly derive from a nested struct? - c++

I have an abstract (templated) class that I want to have its own return type InferenceData.
template <typename StateType>
class Model {
public:
struct InferenceData;
virtual InferenceData inference () = 0;
};
Now below is an attempt to derive from it
template <typename StateType>
class MonteCarlo : public Model<StateType> {
public:
// struct InferenceData {};
typename MonteCarlo::InferenceData inference () {
typename MonteCarlo::InferenceData x;
return x;
}
};
This works, but only because the definition of MonteCarlo::InferenceData is commented out. If it is not commented, I get invalid covariant return type error. I want each ModelDerivation<StateType>::InferenceData
to be its own type and have its own implementation as a struct. How do I achieve this?

You cannot change the return type of a derived virtual method.
This is why your compilation failed when you try to return your derived InferenceData from MonteCarlo::inference().
In order to achieve what you need, you need to use a polymorphic return type, which requires pointer/reference semantics.
For this your derived InferenceData will have to inherit the base InferenceData, and inference() should return a pointer/reference to the base InferenceData.
One way to do it is with a smart pointer - e.g. a std::unique_ptr - see the code below:
#include <memory>
template <typename StateType>
class Model {
public:
struct InferenceData {};
virtual std::unique_ptr<InferenceData> inference() = 0;
};
template <typename StateType>
class MonteCarlo : public Model<StateType> {
public:
struct InferenceDataSpecific : public Model<StateType>::InferenceData {};
virtual std::unique_ptr<Model::InferenceData> inference() {
return std::make_unique<InferenceDataSpecific>();
}
};
int main()
{
MonteCarlo<int> m;
auto d = m.inference();
return 0;
}
Note: if you need to share the data, you can use a std::shared_ptr.

You have to make the return type part of the template arguments:
template <typename StateType, typename InferenceData>
class Model {
public:
virtual InferenceData inference () = 0;
};
Then you can set the return type when you derive from it.

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).

Related

How to inherit abstract behavior from c++ base class

Suppose I want to implement abstract behavior in a base class that is inherited by all derived classes. For example, a function that clones an object, applies some modification to it and returns the cloned and modified object (e.g. transposition, duplication, etc). The following code uses an even simpler function that merely returns the object itself:
class Base
{
public:
virtual Base* yourself ()
{
return this;
}
};
class Derived : public Base
{
public:
...
};
void main()
{
Derived d;
auto result = d.yourself();
}
If I didn't miss something, result will be of type Base*, where the intention clearly is to get an object of type Derived*.
Is there a way to have yourself() return the intended value for all derived classes without overriding it in all places (actually the whole point of inheritance is to implement each behavior only once)?
This issue is fairly common, and you can get around it using templates. Something like this:
template <class T>
class Base
{
public:
virtual T* yourself ()
{
return dynamic_cast<T*>(this);
}
};
class Derived : public Base<Derived>
{
public:
...
};
It's called the Curiously recurring template pattern (CRTP)

Abstract base class using template argument from derived class

I have a base class which provides pure virtual interfaces. I need this to store pointers to derived-class objects in a list of pointers to the base class.
The derived class is created using the template mechanism. The problem is now that if I want to have a virtual interface to return a type which is known only to the derived class, I need to pass it as a template argument as well. This is where the dilemma starts...
template <typename ITEM>
class base {
public:
virtual ITEM* get() = 0;
};
template <typename ITEM>
class derived : public base<ITEM>{
public:
ITEM* get() {...};
};
But when using a template in base I need to know this even when creating a list of base pointers:
base* myList[10] = {derived1, derived2,...}
Of course I don't know that type when I define my list. So I need to get rid of the template in my base class somehow.
EDIT: Got rid of this approach because it wasn't a useful approach at all. So no solution for this issue.
The code you write is not valid; there is not a single base type that is then parameterised like in Java, but a number of base<T> types. There is a way to obtain a wrapper for a truly generic object, and it is called "type erasure". It is used, for example in the implementation of boost::any.
Basically, you have a non-template base class with virtual functions, and then you make a template derived class that implements them. Note that the simplified version shown here does not work if you want to have an array of base objects, because base has pure virtual functions and thus cannot be instantiated (and because the T member of the derived type would be sliced off).
struct base;
template<typename T>
struct derived;
struct base {
virtual ~base();
// In this class we don't know about T, so we cannot use it
// Other operations that delegate to the derived class are possible, though
virtual std::size_t sizeofT() const = 0;
virtual const std::type_info& typeofT() const = 0;
// Since all you want is a pointer in "get", you could write it as a void*
virtual void* getPtr() = 0;
// Otherwise, we can implement this template function here that calls the virtual.
// Note that function templates cannot be virtual!
template<typename U>
U& getAs() {
// Verify that the type is the _same_ (no up/downcasts allowed)
// std::bad_cast is thrown here if U is not the same T used to build this object
derived<U>& meAsU = dynamic_cast<derived<U>&>(*this);
return meAsU.obj;
}
};
template<typename T>
struct derived : public base {
T obj;
// A couple of ctors to initialize the object, and the default copy/move ctors/op=
virtual ~derived();
derived(const T& o) : obj(o) {}
derived(T&& o) : obj(std::move(o)) {}
std::size_t sizeofT() const override {
return sizeof(T);
}
const std::type_info& typeofT() const override {
return typeid(T);
}
void* getPtr() override {
return static_cast<void*>(&obj);
}
};
If you want to use the base type directly as a variable, or in an array or container (vector, list, etc.), you need dynamic allocation - there are no two ways around it. You have two choices, which differ on where to place the responsibility for the dynamic allocation:
You can use the solution above if you limit yourself to having arrays of pointers to base. E.g. an array of std::unique_ptr<base>. The pointed-to objects would be of type derived<something>.
base err1; // Error, abstract class (what would it contain?)
base err2 = derived<int>(2); // Still abstract class, and the int would be sliced off
std::unique_ptr<base> ok(new derived<int>(3)); // Works
std::vector<std::unique_ptr<base>> objects;
objects.push_back(std::make_unique(new derived<int>(5)));
objects.push_back(std::make_unique(new derived<std::string>(2)));
int& a = objects[0].getAs<int>(); // works
std::string& b = objects[1].getAs<std::string>(); // works too
std::string& bad = objects[1].getAs<double>(); // exception thrown
Otherwise, you would have to implement the dynamic allocation in the base/derived classes themselves. This is what classes like boost::any or std::function do. The simplest any object would simply be a wrapper of an unique-ptr of the base class I showed here, with appropriate implementations of operators, etc. Then, you can have a variable of type any x = y; and the class would, inside its constructor, do the required new derived<Y>(y) required.

Casting specialized base pointer to derived pointer that specializes on additional template parameter ("adding on" a specialization)

I'd like to cast a base class pointer to a derived one in order to take advantage of some methods unique to the derived class. Here's an Ideone of a simple example that works:
template<typename A>
class Base {};
template<typename A, typename B>
class Derived : public Base<A> {
public:
void doSomething() {}
};
int main() {
Base<int>* foo = new Derived<int, double>;
static_cast<Derived<int, double>*>(foo)->doSomething();
return 0;
}
Now, the problem is that my foo is actually a member of a templated class,
template<typename A>
class Container
{
public:
Base<A>* foo;
};
and at the time I cast, I don't know what A is:
int main() {
Container<int> container;
container.foo = new Derived<int, double>;
// a lot of code later...
static_cast<Derived< /* ??? */ , double>*>(container.foo)->doSomething();
return 0;
}
Then I thought this might be possible if I could somehow store what A is in my base class, like
template<typename A>
class Base
{
public:
static type template_type = A; // made-up syntax
};
so that I can refer to it like
static_cast<Derived<container.template_type, double>*>(container.foo)->doSomething();
but according to this question it's not possible to store types in C++.
How do I achieve this cast without knowing A?
That is, how do I cast a specialized base pointer to a derived pointer that specializes on an additional template parameter? In less technical terms, I just want to take a Base pointer and tack on the other specialization necessary to form the Derived pointer.
Usually it is not wise to do an up-cast and there is usually a better design that you may use to avoid the need of up-cast at all, but if you really need it, then you may use dynamic_cast to do this.
this operator try to convert from one type to another type dynamically and if conversion is not possible, it will return nullptr. But remember that it only work for polymorphic types(types that have at least one virtual function) so in this case your Base class must be polymorphic(since you are holding a pointer to base class, you possibly need a virtual destructor to allow delete to work on base pointer and this make Base a polymorphic class).
But to remember a type in C++, you have 2 options:
Use typedef:
You may use typedef to hold type information in the class:
template< class A >
class my_class
{
public:
typedef A input_type;
};
template< class T >
void do_something(T const& t)
{
typename T::input_type n;
do_something_on_input_type(n); // possibly overloaded for different input types
}
this approach is really fast and have no overhead in runtime, but you can use it only in cases when you want to do something in compile time. and if the type of pointer is not determined until runtime this approach is not useful.
Use std::type_info
Using this you can actually hold type information with the class:
class Base { virtual std::type_info const& get_type() const = 0; };
class Child : public Base
{
virtual std::type_info const& get_type() const { return typeid(Child);
void child_specific_function() { /**/ }
}
class ChildOfChild : public Child
{
virtual std::type_info const& get_type() const { return typeid(ChildOfChild); }
// ...
};
void do_something(Base* base)
{
if (base->get_type() == typeid(Child))
{
static_cast<Child*>(base)->child_specific_function();
}
}
This sound really interesting but, it is only useful when you know exact type of the object and it does not work for derived types, so this approach work for Child but not for ChildOfChild

Factory pattern for objects that differ in one member datatype?

I keep running into the same conundrum over and over again when I try to implement a factory pattern for something like this:
class Base {
template <typename T>
void doSomethingWithMember(T){
}
void doing(){
doSomethingWithMember(this->a);
}
private:
int a;
};
class A: public Base {
double a;
};
class B: public Base{
float a;
};
struct Dictionary {
typedef Base* (*FunctionPointer)(void);
std::map <int, FunctionPointer> fmap;
template <typename Target>
static Base* construct() {
return new Target();
}
Dictionary() {
fmap.insert(std::make_pair(0, &Dictionary::construct<A>));
fmap.insert(std::make_pair(1, &Dictionary::construct<B>));
}
Base* Call( int i ) const {
std::map<int, FunctionPointer>::const_iterator entry = fmap.find( i );
return entry == fmap.end() ? new Base() : (*entry->second)();
}
};
The problem is, I cannot define a in Base because in best case it gets hidden. But without a definition of a i cannot implement a function for the inheritors to cope with their a. What I also tried was implementing Base as a template which led to the problem that I always had to know the returning data type (int, double, float) when creating an object trough the dictionary - saying I had no basic object type for Base<int>, Base<float>, Base<double>. And I do need the dictionary to give me an object according to i without me knowing anything else but i.
Your problem with making Base a template is that you lost your common base. However, you can get that back by making the derived class the template. E.g.:
struct Base {
virtual ~Base() { }
};
template<typename T>
struct Derived : Base {
private:
T a;
};
With the above, you can return a Base * while having your factory construct Derived<X>. Your construct() function would look something like this:
template<typename T>
static Base *construct() {
return new Derived<T>();
}
Any functions that need to manipulate a would be put in Derived<T>, and because Derived is a template, you would only have to implement them once.

C++ - Use inferred template argument from constructor as template argument throughtout class

I'd like to use the inferred type from the constructor argument as template arguments throughout the rest of my class. Is this possible?
Something like this:
class AnyClass
{
public:
template<Class C>
AnyClass(C *c) {
//class C is inferred by constructor argument
}
// constructor argument is used as argument in other template types
nestclass<C> myNestedClass;
void randomfunction(C *randonarg) {
}
}
Details:
Here's the thing. I'm trying to initialize my base type given the type of the inheriting class. In the case below DerivedA inherits from Base, but DerivedB inherits from DerivedA, therefore from what I understand the value of this in the constructor of Base (found in DerivedA) will actually be a pointer to DerivedB therefore the inferred type in Base will be of type DerivedB. However I'd like to use this type throughout the rest of my Base class and not just limit it to the constructor.
class Base {
// type T derived from inheriting class
template<T>
Base(T *) {};
//like to use other places
void randomfunction(T *arg1) {
//does something with type T
};
}
class DerivedA : publicBase {
DerivedA() : Base(this) { //this should be a pointer to DerivedB, since it is inherited
//from DerivedB.
}
}
class DerivedB : class DerivedA {
//anything
}
**My main goal is to use the inheriting class type in my base class. I realize this is sort of a different qst, but I was thinking my solution would be found somehow in my original question.
I'm thinking using a go-between method (similar to the function proposed below) but not sure if it will work.
Thanks for the help!
No.
But you can make your entire class a template class, and create a factory function that does type deduction to generate your template class.
template<typename C>
class AnyClass {
public:
AnyClass( C* c );
std::vector<C> vec;
};
AnyClass<C> make_any_class( C* c ) {
return AnyClass<C>(c);
};