Reputation: 9708
I have a templated class,
template<typename T>
class TClass
{
public:
//functions here
};
class Holding {
public:
private:
TClass<T> m_item; //don't want this
};
int main() {
Holding hd;
//do whatever
return 0;
}
I want a sort of instance variable in Holding but don't want to make Holding a template class. What are my design options?
Upvotes: 2
Views: 71
Reputation: 59811
You can use type-erasure if the possible holdings are similar enough.
#include <memory>
class HeldType {
public:
virtual void myfunc() = 0;
virtual ~HeldType() {}
};
template<typename T>
class HeldTypeModel : public HeldType {
public:
HeldTypeModel(const T& t) : data_(t) {}
void myfunc() { data_.myfunc(); }
private:
T data_;
};
class TClass {
public:
TClass() : x_(nullptr) {}
template<typename T>
void set_t(const T& t) {
x_.reset(new HeldTypeModel<T>(t));
}
std::unique_ptr<HeldType> x_;
};
class model {
public:
void myfunc() {}
};
int main()
{
TClass x;
x.set_t(model{});
return 0;
}
You need to figure out what are the commonalities between all the possible T. You probably also want to add some functions to get the typeid
and to cast out the actual type etc. Have a look at boost::any
.
If you are more on the experimental side of things, you can have a look at Boost.Type Erasure, which takes away some of boiler-plate, but is not yet part of an official release.
Upvotes: 0
Reputation: 7773
I might not understand your question properly. Basically, you have a template class TClass which needs to be configured through a template parameter. You then have Holding which owns a TClass but you don't want to make Holding a template for whatever reason.
This means that Holding needs to statically define what's the template parameter
TClass<SomeClass> m_item;
Now, you say in code you don't want this... I'm not sure if you don't want to provide a template parameter or provide T. If it's T, the code above would fix your issue. Otherwise, you'll need to use a typedef to remove the template argument and have a "template-less" type, such as:
typedef TClass<int> intTClass; // replace int by whatever param you want
which can then be used as
class Holding {
public:
private:
intTClass m_item; //don't want this
};
Upvotes: 0
Reputation: 361582
It looks like you want to hold any type. If that is really the case, then you could use boost::any
:
class Holding {
public:
private:
TClass<boost::any> m_item; //you want this?
};
If you don't use Boost, then you could implement any
yourself or search for its implementation on this site or use google.
Upvotes: 2
Reputation: 171147
Derive TClass
from a non-template base class B
and have Holding
hold a pointer (perhaps std::unique_ptr
) to B
.
Upvotes: 1