Template pointer without knowing the type - c++

template <typename T>
class Container
{
private:
T data;
public:
Container(T newData) : data(newData) {}
T getData() {return data;}
};
int main()
{
Container* numContainer=new Container<int>(5);
//Do something with numContainer
delete numContainer;
}
This doesn't compile since the type of the Container pointer must be specified, such as int.
This can, as I found out after some quick googling, be dealt with by creating a ContainerBase class which is not a template and let Container derive from it. Letting the pointer be of type ContainerBase will however not let me use methods such as getData() since it returns type T and can therefore not be declared in the ContainerBase class.
Can I somehow have a pointer which can point to an instance of a template class of any type, even if the class contains methods such as in the example above?

Can I somehow have a pointer which can point to an instance of a template class of any type, even if the class contains methods such as in the example above?
No you can't, for your template class to be instantiated the compiler must know the type of T. Think of a class template as a blueprint of a class and not as a concrete definition of a class. For every type you specify for your template class (e.g., Container<int>) the compiler generates a separate definition. The compiler when it sees the name of your template class (e.g., Container) can't deduce its type out of thin air.
IMHO, The best you can do in order to avoid explicitly specifying every time the type of the template is to use aliases like the example below:
template <typename T>
class Container {
T data;
public:
Container(T const &newData) : data(newData) {}
T getData() const {return data;}
};
using iContainer = Container<int>;
int main() {
iContainer* numContainer=new iContainer(5);
//Do something with numContainer
delete numContainer;
}
Or use runtime polymorphism as you've already mentioned in combination with use of dynamic_cast like the example below:
class BaseContainer {
public:
virtual ~BaseContainer() {}
};
template <typename T>
class Container : public BaseContainer {
T data;
public:
Container(T const &newData) : data(newData) {}
T getData() const {return data;}
};
int main() {
BaseContainer *numContainer = new Container<int>(5);
Container<int> *ptr = dynamic_cast<Container<int>*>(numContainer);
if(ptr) std::cout << ptr->getData() << std::endl;;
delete numContainer;
}
LIVE DEMO

Related

Create an instance given pointer type in template

Is there a way to call the constructor of a class, given the pointer-type of that class type as the template parameter?
MyClass<AnotherClass*> => how to call the default constructor of AnotherClass in MyClass?
This one does obviously not work (doesnt compile), because in GetNew the new T and the return type T don't fit together. What would be needed is some kind of "type dereferencing" to come to the class type, given the pointer type.
class AnotherClass
{};
template <class T>
class MyClass
{
public:
// this does obviously not compile
virtual T GetNew()
{
return new T; // how let T be AnotherClass* and to create an AnotherClass instance here?
}
};
int main()
{
// this does not compile:
MyClass<AnotherClass*> tmp; // here, AnotherClass is **pointer** type
AnotherClass* a = tmp.GetNew();
}
A workaround would be to use the class type as the template parameter and use poiter types as return types. But this changes the interface, so I would still like a solution to pointer template type.
class AnotherClass
{};
template <class T>
class MyClass2
{
public:
virtual T* GetNew()
{
return new T;
}
};
int main()
{
// this does work:
MyClass2<AnotherClass> tmp2; // here, AnotherClass is **not** pointer type
AnotherClass* b = tmp2.GetNew();
}
Another workaround could be to use a factory or similar, but I would like to use the default constructor without additional helping structures.
You can use std::remove_pointer to get the type pointed to.
Provides the member typedef type which is the type pointed to by T, or, if T is not a pointer, then type is the same as T.
E.g.
virtual T GetNew()
{
return new std::remove_pointer_t<T>;
}
If you require the parameter to MyClass to be a pointer, you can specialise it for pointers and leave it undefined for other types
template<typename>
class MyClass;
template<typename T>
class MyClass<T*>
{
public:
virtual T* GetNew()
{
return new T;
}
};
int main()
{
// MyClass2<AnotherClass> tmp1; // compile error
MyClass2<AnotherClass *> tmp2; // fine
AnotherClass* b = tmp2.GetNew(); // GetNew returns the exact type parameter
}

C++ inheritance in template parameter

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.

Run-Time Checking of a Cast from a void*

Say that I have a void* containing a pointer to an unknown class. I want to use dynamic_cast to do run-time checking on the type of class I actually have. For example:
class Foo {};
void* bar = new Foo;
If I attempt to do dynamic_cast<Foo*>(bar) I get:
'void *': invalid expression type for dynamic_cast
However I need dynamic_cast because in my actual situation I'm not sure that bar is in fact a Foo*.
I've read here that one solution to this is to create a base class for all objects that bar could contain, reinterpret_cast to a pointer to that base class, and then try to dynamic_cast from that object pointer to Foo.
This is difficult for me because the objects that may be stored in bar are not all under my control. (And cause trying to recreate Java gives me heartburn.) Is there another way to do this?
dynamic_cast is use to cast down a polymorphic object to a class that has the type of the object you're trying to cast as it's parent.
void* is completely different from that.
with a pointer to void, you are literally stripping every type information away.
dynamic_cast know that there's a base class and can do type checking through RTTI.
When you cast down a void pointer, you're saying to the compiler: "yeah you know this place in the memory? well, use it as this type" and if the memory is invalid, UB is invoked.
you have three choices here.
Option 1
Use an interface.
Well, a polymorphic base class is the only way to do a dynamic_cast. There is no other way, no hacks, it's the only way. Simple as that.
struct Base { virtual ~Base() = default; };
struct Derived : Base {};
// ...
void test (Base* base) {
auto derived = dynamic_cast<Derived*>(base);
if (derived) {
// derived is valid here.
}
}
Option 2
Identify the type with the pointer
I use a method to have a unique identifier per type and use the identifier to validate the cast. Done without any RTTI
using type_id_t = void(*)();
template <typename T> void type_id() {}
// now we can use a map or a vector.
std::vector<std::pair<type_id_t, void*>> vec;
template<typename T>
void insertToMyVector(T* obj) {
vec.emplace_back(type_id<T>, obj);
}
template<typename T>
T* getObj(int index) {
auto item = vec[index];
return static_cast<T*>(item.first == &type_id<T> ? item.second : nullptr);
}
// ...
int main () {
auto foo = new Foo;
insertToMyVector(foo);
auto maybeFoo = getObj<Foo>(0);
if (maybeFoo) {
// you have a valid Foo here
}
}
Option 3
Generate derived class for any type
This one is quite useful as it can hold any type while keeping type safety. I look like solution 1 but offer more flexibility. The trick it to generate a derived class for any type using templates. The advantage is you can hold any type, but may complexify you cade a bit.
struct Base { virtual ~Base() = default; };
template<typename T>
struct Derived : Base {
Derived(T&& obj) : _obj{std::move(obj)} {}
Derived(const T& obj) : _obj{obj} {}
T& get() {
return _obj;
}
const T& get() const {
return _obj;
}
private:
T _obj;
};
// ...
void test (Base* base) {
auto derived = dynamic_cast<Derived<int>*>(base);
if (derived) {
int i = derived->get();
// derived is valid here, and we can safely access the int
}
}
To ensure dynamic_cast compiles and works, you should create an abstract or interface class with a virtual method.
#include <cassert>
class Bar
{
public:
Bar() = default;
virtual ~Bar() = default;
};
class Foo : public Bar
{
public:
Foo() = default;
virtual ~Foo() = default;
};
int main()
{
Bar* bar = new Foo;
Foo* foo = dynamic_cast<Foo*>(bar);
assert(foo != nullptr);
}
As I understand it you want a polymorphic object but no common base class.
There is already a fairly standard idiom for this - it's called boost::any.
A boost::any carries your object plus some type information. The interface allows you to query the type and to attempt to cast the any to the type you're looking for.
http://www.boost.org/doc/libs/1_59_0/doc/html/any.html

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.