Mat
Mat

Reputation: 11883

C++ generic classes & inheritance

I'm new to generic class programming so maybe my question is silly - sorry for that. I'd like to know whether the following thing is possible and - if so, how to do it

I have a simple generic class Provider, which provides values of the generic type:

template <class A_Type> class Provider{
public:
A_Type getValue();
    void setSubProvider(ISubProvider* subProvider)
private:
A_Type m_value;
ISubProvider* m_subProvider;
};

The getValue function shall return m_value in case of m_subProvider is NULL. But if SubProvider is not Null, the value shall be calculated by the SubProvider class.

so subprovider must be of generic type too, but i create it as an abstract class without implementation:

template <class A_Type> class ISubProvider{
public:
virtual A_Type getValue() = 0;
};

now I want the actual implementations of ISubProvider to be nongeneric! for example I want to implement IntegerProvider which returns type Integer

class IntegerProvider : public ISubProvider{
   int getValue(){return 123;}
};

and maybe a StringProvider:

class StringProvider : public ISubProvider{
  string getValue(){return "asdf";}
};

now - how can I code the whole thing, such that i can use the

void setSubProvider(ISubProvider* subProvider)

function of class Provider only with a subprovider that corresponds to the generic type of Provider?

for example, if i instanciate a provider of type int:

Provider<int> myProvider = new Provider<int>();

then it shall be possible to call

myProvider.setSubProvider(new IntegerProvider());

but it must be impossible to call

myProvider.setSubProvider(new StringProvider());

I hope you understand my question and can tell me how to create that code properly :)

Thank you!

Upvotes: 2

Views: 8870

Answers (3)

CB Bailey
CB Bailey

Reputation: 792129

C++ has templates (class templates and function templates), not generics.

Given this declaration:

template <class A_Type> class ISubProvider;

you can't do this:

class IntegerProvider : public ISubProvider{
    int getValue(){return 123;}
};

because ISubProvider is not a class, it's a class template.

You can though, do this.

class IntegerProvider : public ISubProvider<int> {
    int getValue(){return 123;}
};

I think that this is what you want to do, in any case.

This also won't work for the same reason.

template <class A_Type> class Provider {
public:
    A_Type getValue();
    void setSubProvider(ISubProvider* subProvider)
private:
    A_Type m_value;
    ISubProvider* m_subProvider;
};

You have to do something like this.

template <class A_Type> class Provider {
public:
    A_Type getValue();
    void setSubProvider(ISubProvider<A_Type>* subProvider);
private:
    A_Type m_value;
    ISubProvider<A_Type>* m_subProvider;
};

Now you have achieve what you wanted in that you must provide a pointer to an ISubProvider instantation for the same template type parameter as the Provider class template.

Note, however, that you haven't really gained anything by using a base class templated on type in this case.

Upvotes: 5

BostonLogan
BostonLogan

Reputation: 1596

You need to derive from your ISubProvider in the following way

class IntegerProvider : public ISubProvider<int>
class StringProvider : public ISubProvider<string>

And so on

Also change you class declaration

template <class A_Type> class Provider{
public:
A_Type getValue();
    void setSubProvider(ISubProvider<A_Type>* subProvider)
private:
A_Type m_value;
ISubProvider<A_Type>* m_subProvider;
};

Upvotes: 2

lyricat
lyricat

Reputation: 1996

If you drop the seperate idea of a provider/sub-provider and just create a single provider, your problem solves itself.

template <class A_Type> class Provider{
  typedef Provider< A_Type > my_type;

public:
  A_Type getValue();
  void setSubProvider(my_type* subProvider)
private:
  A_Type m_value;
  my_type* m_subProvider;
};

Upvotes: 0

Related Questions