Reputation: 11883
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
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
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
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