I need to pass template as function argument, but template must accept all inherited objects.
For example:
template <class T>
class Template {
public:
Template() {}
};
// IMPORTANT: must accept all children of "Base"
class Test {
Template<Base> *pointer;
public:
Test(Template<Base> *pointer) {...}
};
main() {
Template<Base> *base = new Template<Base>();
Template<Child1> *child = new Template<Child1>();
Test *test1 = new Test(base); // WORKING
// NEXT LINE IS IMPORTANT:
Test *test2 = new Test(child); // ERROR: no matching function for call to 'Test::Test(Template<Child1>*&)'
}
class Base {...};
class Child1 : public Base {...};
class Child2 : public Base {...};
..
I need the most effective way, how to store template in "Test" class, that will accept all children classes. I have lot's of children classes.
1) Is it possible to make some up casting (static_cast) for Child class in argument? It will be good to use it inside of "Template" or inside of "Test" class. Not, when creating new "Test" object, because there will be lot's of new objects.
2) Or pass argument without template argument Test(Template *pointer) {...}?
Or how to solve it?
The reason that the thing you want to do doesn't work is because template types don't observe inheritance in typename parameters.
Template<Base> *base
and
Template<Child1> *child
are completely different types. Trying to use one in place of the other is like trying to pass an int to a function that has a string parameter.
That said, I believe you have two viable options here.
#1 Make Test a template too
One option would be to make Test a template too:
template <typename T>
class Test {
T *pointer;
public:
Test(T *pointer) {...}
};
This would allow the Test object to work with whatever object was passed to it.
#2 Use an interface
Alternatively, by creating an interface, and implementing that interface in Template, you can pass your interface to the Test class:
/**
* Interface that declares the virtual methods that
* will be used by your Test class.
*/
class ITemplate {
public:
virtual ~ITemplate() {}
// Define your methods here.
virtual void Foo() = 0;
virtual void Bar() = 0;
virtual void Baz() = 0;
}
/**
* Concrete ITemplate implementation.
*/
template <class T>
class Template : public ITemplate {
public:
Template() {}
virtual ~Template() {}
virtual void Foo() override {}
virtual void Bar() override {}
virtual void Baz() override {}
};
class Test {
ITemplate *pointer;
public:
Test(ITemplate *pointer) {...}
};
This has the advantage that you can modify your Template class without affecting your Test class, because the Test class works with ITemplate interfaces instead of concrete objects. The downside of this is that you incur the cost of virtual function lookups, which may be undesirable if you're trying to write extremely efficient code.
1) Is it possible to make some up casting (static_cast) for Child class in argument? It will be good to use it inside of "Template" or inside of "Test" class. Not, when creating new "Test" object, because there will be lot's of new objects.
I don't exactly understand what you're suggesting. It won't be possible to cast an unrelated pointer to another.
2) Or pass argument without template argument
No. Templates can not be function arguments.
What you could do, is make Template<T> implicitly convertible to other instances of Template:
template <class T>
class Template {
public:
// ...
template<class U>
Template(const Template<U>&);
};
Depending on how the converting constructor is implemented, it may impose restrictions on U.
And further, if you were to store a Template<Base> instance within Test instead of a pointer:
class Test {
Template<Base> member;
// ...
};
Then, you could accept the Template<Base> by value (to copy) or by rvalue-reference (to move) to the constructor. A Template<Child> would be implicitly converted to Template<Base>:
class Test {
Template<Base> member;
public:
Test(Template<Base> argument) {/* ... */}
};
This approach is the same as is used to allow implicit up casting of the standard smart pointer types.
Related
Is it possible to check, through a base class pointer, whether different derived template classes are specialization of the same template class?
This is achievable through introducing an intermediate non-template base-class. However, i would like to know whether this pattern is avoidable when the sole purpose of this intermediate class is for identification:
class A{}
class B_base : public A{}
template<T>
class B : public B_base {}
// There may be other derived classes of A
template<T>
class C: public A{}
void main() {
// ... some vector of pointers to A derived objects
std::vector<A*> v;
for(auto& i : v){
// Check whether i is any specialization of B through a
// dynamic_cast to the intermediate class
if(dynamic_cast<B_base*>()){
// This is a B_base object,
}
}
}
Ideally, i would like something like this, to avoid the intermediate class.
class A{}
template<T>
class B : public A{}
// There may be other derived classes of A
template<T>
class C: public A{}
void main() {
// ... some vector of pointers to A derived objects
std::vector<A*> v;
for(auto& i : v){
// Check whether i is any specialization of B
if(templateTypeId(i) == templateTypeId(B*)){
// This is a B object with some unknown specialization
}
}
}
Different specializations of a template are entirely unrelated types for most purposes. Template argument deduction can deduce a template and its arguments from such a type, but that happens entirely at compile time. There is no guaranteed run time information that can tell whether a class is a specialization of a given template, whether two classes are specializations of the same template, etc.
So you would need to set up a way to test this yourself, but your intermediate class method is not the only option. The most straightforward way would be to put a way to test it into the base A class:
class A {
public:
virtual ~A() = default;
virtual bool is_B() const noexcept { return false; }
};
template <class T>
class B : public A {
public:
bool is_B() const noexcept override { return true; }
};
Though this gets a bit ugly if there are several different B-like categories to test for, and doesn't work if it should be possible to extend A with new subtypes, and then test for those subtypes in a similar way.
Another idea would be to associate the type check with an object address:
struct type_tag {
constexpr type_tag() = default;
type_tag(const type_tag&) = delete;
type_tag& operator=(const type_tag&) = delete;
};
class A {
public:
virtual ~A() = default;
virtual bool matches_type(const type_tag&) const
{ return false; }
};
inline constexpr type_tag B_tag{};
template <class T>
class B {
public:
bool matches_type(const type_tag& tag) const override
{ return &tag == &B_tag; }
};
This pattern also allows for categories of subtypes that don't come from just one template. It also doesn't prevent a new class from "lying" about its own type, if that might be a concern, but it might be best not to try to prevent that, but let any implemented derived class be responsible for its own behavior, which might mean it wants to act "almost exactly like" some other type.
May be a better design is to add required virtual functions to interface A, so that you can invoke them directly on A* without guessing the derived class. The latter is an anti-pattern because it defeats the purpose of polymorphism: the idea that a piece of code can work with object of different classes without knowing their exact type. You may as well put objects of different types into different containers and not use ploymorphism based on virtual functions at all.
I want to know whether it is possible or not.
I have a class in one project.
class A { ...
void CreateInternal(void);
B* m_pData;
... }
void A::CreateInternal(void)
{
m_pData= new B;
}
and in other project, i add C class and want to make it in A::CreateInernal(void) like this...
void A::CreateInternal(void)
{
m_pData = new C; // ex) B is base class of C
}
Of course, i can make Class A to template class, however, i do not want it. I want to use it last. ( Suppose that dependency or other build error is free )
typename<class T>
class A { ...
void CreateInternal(void);
T* m_pData
... }
void A<T>::CreateInternal(void)
{
m_pData = new T;
}
I just want to register Class B or Class C in Class A.
Is it possible??
Thank you for your reply!
As denoted in the comments:
You don't want to make A a template class.
You the classes you want to create instances of share a common base class, which is the type of the member pointer as well (precondition for the following!).
So you can make createInternal a template function instead:
template <typename T>
void A::createInternal()
// ^^^ A still is a normal class!
{
m_data = new T();
// (will fail if T is a different type NOT inheriting
// from the base class in question)
}
Side note: Normally, if template functions are provided inside classes, you would have to implement them in the header file (typically at least, there are ways around...), if createInstance is private, though, and you don't call it from public inline functions, you can safely implement it in the source file as well as this file will be the only location the template ever is used.
You can even go a step further and allow to call all possible constructors by use of a variadic template:
template <typename T, typename ... TT>
void A::createInternal(TT&& ... tt)
{
m_data = new T(std::forward(tt)...);
// (will fail, if there is no matching constructor
// for the arguments provided)
}
OK, you now have to specify which instance you want to create:
void A::f()
{
createInternal<B>();
createInternal<C>();
}
I assume this being acceptable as you need to be able to tell somehow which type you actually want to create.
The alternative would be different functions for different classes (createInternalB, createInternalC), but that certainly is less elegant.
Side note:
Is it possible??
Even if your classes did not share a common base class, you still could store your objects created in a std::variant or, if you happen to compile pre-C++11, even in a union (but you need to take care yourself about which type actually is stored – in this respect, std::variant is just much safer, so prefer it whenever possible).
Update on new comments:
If you want to be able to create arbitrary objects within A without having to know which one actually is created, now offering two further alternatives:
In first variant you could make createInternal virtual in A (possibly even pure virtual) and then override in derived classes to provide the objects suiting your needs.
In second variant you provide an instance of some object provider class; assuming D is the base class of both B : public D and A : public D, so then the solution might look similar to this:
class A
{
public:
class ObjectProvider
{
public:
virtual ~ObjectProvider() = default;
public: virtual D* createInstance() = 0;
};
template <typename T>
class TheObjectProvider : public ObjectProvider
{
public:
D* createInstance() override
{
return new T();
}
};
A(std::unique_ptr<ObjectProvider> p)
: objectProvider(std::move(p))
{ }
private:
std::unique_ptr<ObjectProvider> objectProvider;
std::unique_ptr<D> m_data;
void createInternal()
{
m_data = objectProvider->createInstance();
}
};
Usage:
A ab(std::make_unique<A::ObjectProvider<B>());
// your own custom object provider:
class OP : public A::ObjectProvider
{
public:
C* createInstance() override { return new C(); }
};
A ac(std::make_unique<OP>());
The std::unique_ptr as parameter (although in general, it is not recommended to use smart pointers for) now has an important function: It indicates that the class will take ownership of the object passed, i. e. is a sink in Herb Sutter's wording – see his GotW91).
If you have a most commonly used data type (e. g. B), you could provide an overloaded default constructor providing an object provider for this type (or possibly the base type D, if not being abstract).
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.
I've got a fairly unique situation.
I've got a structure resembling the following code, where a class template inherits from its own template argument, which may be a certain BaseClass, or any of its subclasses.
class BaseClass {
...
virtual void BaseMethod();
};
class DerivedClass {
...
virtual void BaseMethod(); // DerivedClass Overrides some of baseclass's methods
void DerivedMethod(); // And it has a few of its own
};
template <class T>
class ClassTemplate : public T {
...
// Some validation to ensure that this class template extends
// either BaseClass or one of its derived classes
void ValidateTemplate(const BaseClass& c) {}
...
}
The point where this becomes tricky is when I want to take a template class argument that is templated after the baseclass, or one of its subclasses:
void func(ClassTemplate& c) { ... c.BaseMethod(); }
Of course, this doesn't compile as its missing its template arguments. However, I'm looking for a solution that will function like the following, without having to actually specify the following function overloads:
void func(ClassTemplate<BaseClass>& c) { ... c.BaseMethod(); }
void func(ClassTemplate<DerivedClass>& c) { ... c.BaseMethod(); }
On top of that, one of my other classes contains a list of ClassTemplate pointers:
class ClassWithList {
std::list<ClassTemplate<BaseClass>*> l;
...
}
With the above, I want the list l to contain both ClassTemplate<BaseClass> objects, and ClassTemplatE<DerivedClass> objects. This has the same root problem - hoping that the latter could be interpreted as the former, as is the case for most implicit conversions in C++. Is this particular kind of conversion possible to do with templates? Or is there an alternate workaround?
Notes:
In func, none ofDerivedClass's functions are used - just like if I had taken a BaseClass argument, I want to be able to access its public members.
However, it is important that I don't take BaseClass as an argument. This is because I need to access members of the ClassTemplate object, which are unique to ClassTemplate itself.
Additionally, I can't resort to using multiple inheritance (Have DerivedClass subclass both ClassTemplate and BaseClass) as this will result in diamond inheritance, thus creating an inheritance hierarchy too complicated for simple virtual inheritance.
From your description, it sounds like you want a function template:
template <typename T>
void func(ClassTemplate<T>& c) { ... c.BaseMethod(); }
For handling the list case, one option is to have a third class that you use as the interface:
struct ClassTemplateBase {
virtual void doSomething() = 0;
};
template <class T>
class ClassTemplate : public T, public ClassTemplateBase {
// ...
}
then you can have a std::list<ClassTemplateBase *>. This avoids the diamond inheritance issue.
Have a base class A, and a derived class B which overrides function template Func:
class A
{
A() {...};
~A() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
class B : public A
{
B() {...}
~B() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
(Note that Func is non-virtual, given the lack of support in C++ for templated virtual functions.)
Now have a mainprog API, class M:
class M
{
M(boost::shared_ptr<A> &pInterfaceInput): pInterface(pInterfaceInput)
{}
template <class T>
Evaluate(const String &sInput, T &tResult)
{
pInterface->Func<T>(sInput, tResult);
}
private:
const boost::shared_ptr<A> pInterface;
};
I want the function Evaluate here to support calls to functions on base class A or any of its derived classes (such as B). This class was written with polymorphism in mind before I re-designed class A and B to have templated functions.
Now the problem here is that if I pass a shared pointer of the base type to the derived type then Func of the base class will be called, not the derived class being pointed to.
How do I get around the lack of dynamic polymorphism here?
I've considered making class M a class template on the shared pointer type and having a static_cast in the constructor to ensure this type is of the base class type (A) or of a derived class.
What's the nicest way to do this? I'd prefer not to modify classes A and B to get around this problem but all suggestions are welcome.
Thanks.
Sounds like a double dispatch problem. Perhaps this would be a good place to implement the visitor pattern?
For example, create a class Evaluator, and for each T a subclass ConcreteEvaluator<T>. Give A and B methods that visit the Evaluator. Something like:
class Evaluator
{
virtual void visit_A(A* object);
virtual void visit_B(B* object);
};
template <typename T>
class ConcreteEvaluator : public Evaluator
{
public:
String* input_reference;
T& result_reference;
ConcreteEvaluator(String& input_reference_,T& result_reference_) :
input_reference(input_reference_),
result_reference(result_reference_) {}
virtual void visit_A(A* object) {
object->Func(input_reference,result_reference);
}
virtual void visit_B(B* object) {
object->Func(input_reference,result_reference);
}
}
class A
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_A(this);}
...
}
class B
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_B(this);}
...
}
For each subclass of A, a new method must be added to ConcreteEvaluator, so that this technique works best if A's class hierarchy is stable. And for each subclass of A, it must have an apply_evaluator function defined properly.
On the other hand, this may be total overkill. For about the same amount of work, you could always just pay the price to update M::Evaluate:
class M
{
...
void Evaluate(const String& sInput, T& tResult)
{
// try to downcast to each subclass of A. Be sure to check
// sub-subclasses first
try
{
dynamic_cast<B*>(pInterface.get())->Func(sInput, tResult);
return;
}
catch (std::bad_cast& ) { }
...
// nothing worked. It must really be an A
pInterface->Func(sInput,tResult);
}
...
};
I've show in the question Templatized Virtual function how to use type erasure to get some of the effects of virtual member function. Depending on what you want to do in Func(), you can use the same technique here.