I would like to know if it'd be possible (and if, how) to create a pointer of X value
Now, let's say I know which types would be possible to be assigned in this pointer.
For example, a pointer of X value (of course feel free to change the name of this value), that'd be able to point to variables of string, bool and a custom class
Usually what you describe is a bad idea.
void* works, for marginal values of works. It throws out all type safety, requiring you to keep track of it.
Creating a root type sort of works, but it doesn't work for primitive types, and is rather intrusive.
A boost::variant< bool*, std::string*, MyClass* > is a variable that can contain a pointer to any one of these 3 types (bool, std::string or MyClass). You will probably find it challenging to use, because it enforces type safety, and the syntax can get annoying.
Similarly, a pointer to boost::variant< bool, std::string, MyClass > may be what you want, but it doesn't let you point to bool variables you aren't fooling around with.
With full C++11 support, union can contain arbitrary types, together with an enum can let you do something very much like a boost::variant. As a downside, this requires the thing you be pointed to be a union. With or without full C++11 support, a union of pointers is reasonable. In both cases, you'll have to track the type manually and keep it in sync.
What you really need to think about is "why am I asking this?", because as with many questions, the motivation matters. You may not be asking the right question.
I learned a new expression today, so I'm going to use it, "This is an XY question", You want to do X, so you think the solution is Y, therefore you ask how to do Y. You PROBABLY should ask how to do Y instead. It's a bit like you find your front wheel on the car punctured, and you go talk to the mechanic, but you don't ask "how do I fix a puncture", you ask "How do I undo a wheelnut", and only after you've removed all wheelnuts and the car has fallen over do you realize that you should have put a jack under the car to be able to get the wheel off without the car falling over...
Sure, there are void pointers and unions, that's no big deal. However, you still need to know what your pointer is actually pointing at, otherwise you'll have bloody mess.
So generally, in C++, you probably shouldn't do that.
What you should do is wrap your "thing" in another object, that knows what the content is, and can handle it. That way, you don't have some other thing maintainng state of what the object is and how to use it.
For example, we can have this:
class AnyThing
{
public:
virtual ~AnyThing();
virtual std::string ToString() = 0;
... // other things you want to do with your "things".
};
class IntThing: public AnyThing
{
private:
int value;
public:
virtual std::string ToString() { ... convert int to string ... }
};
class StringThing : public Anything
{
private:
std::string value;
public:
virtual std::string ToString() { return value; }
}
You can use a pointer to void.
If you want a pointer that can only be used to point at those three types, then I see three options:
Create a wrapper class for each type that derives from some base-class:
class Thingy { protected: Thing() {} };
class BoolThingy : public Thingy { bool x; }
class StringThingy : public Thingy { String x; }
class CustomThingy : public Thingy { Custom x; }
...
Thingy *p = new BoolThingy;
Create a smart-pointer class, overloading assignment operators that take bool *, String *, Custom *, and also overloading the * operator (although what that would do, I don't know!)
Use a variant class (e.g. boost::variant).
But with any of the options, it's not clear how such a thing would be useful...
void* has the property to point to any data type. It actually works as a container or cubboard in which you put your variable of any data type and then pass the void* to a function.
You must know the data type of the data you passed, in order to use it.
For Example:
int main()
{
int a;
void *x=&a;
func(x);
....
}
void func(void *argument)
{
int i=*(int *)argument;
....
}
If you know the types before hand and they do not have constructors. Then you can use a union.
class CustomClass {};
union MyType
{
char const* a;
bool b;
float c;
};
MyType stuff;
MyType* ptrToStuff = &stuff;
int main()
{
ptrToStuff->a = "Plop";
ptrToStuff->b = false;
ptrToStuff->c = 12.0;
}
Boost also has an ANY type.
You can store anything in it.
boost::any x = 12;
x = new CustomClass;
x = new std::string("Hi There");
x = std::string("Plop"); // even works without pointers.
You can have a pointer to any type (object, pointer, primitive type etc.) but you can not have a pointer to a reference.
NO you cannot have a pointer pointing at objects of unspecified type. The whole point of a pointer is that it points at objects of specific type. int*x points at an int, A*a points at an A.
What you can do, of course, is to have a variable of type void* that points at nothing at all (void), but can hold any address. If you somehow remember what it is the address of, then you can use a static_cast<> to cast to an appropriate pointer. Alternatively, you can use dynamic_cast<> to find out at run-time whether your void* points to a given type. This could be implemented as follows
struct AnyPointerWrapper
{
struct null_pointer {};
struct wrong_pointer_type {};
AnyPointerWrapper() : ptr(0) {}
AnyPointerWrapper(AnyPointerWrapper const&) = default;
AnyPointerWrapper&operator=(AnyPointerWrapper const&) = default;
template<typename T>
explicit AnyPointerWrapper(T*p)
: ptr(p) {}
template<typename T>
AnyPointerWrapper&operator=(T*p)
{ ptr=p; return*this; }
bool is_null() const
{ return ptr==0; }
template<typename T>
bool is() const
{ return dynamic_cast<T*>(ptr) != 0; }
template<typename T>
T* pointer()
{
if(p==0) throw null_pointer;
T*p = dynamic_cast<T*>(ptr);
if(p==0) throw wrong_pointer_type;
return p;
}
private:
void*ptr;
};
and used like this
int X;
AnyPointerWrapper a;
assert(a.is_null());
a = &X;
assert(a.is<int>());
int*p = a.pointer<int>();
(you can add more functionality including support for const pointers). Note, however, that the dynamic_cast<> is not trivial, i.e. incurs some performance penalty. Note also that AnyPointerWrapper is not a pointer: you cannot use the -> operator to call a member function of the object whose address is stored in AnyPointerWrapper::ptr; it is merely a wrapper from which you can get an appropriate pointer.
Related
I am trying to convert a void pointer to a dynamic type.
For example, I passed double variable to test1 function which I expected the sum function will work. But I got C2664 cannot convert argument error on sum(*reinterpret_cast<myType*>(tmp)).
If I using this, it will work.
double c= *reinterpret_cast<double*>(tmp);
sum(c);
How do I fix this?
void sum(double a)
{
cout << "sum:" << a+10 << endl;
}
void test1(void* tmp)
{
typedef decltype(tmp) myType;
sum(*reinterpret_cast<myType*>(tmp));
}
int main()
{
double a = 87.7;
test1(&a);
return 0;
}
First of all, dynamic type is really only meaningful when you're using inheritance. For example, if you have code like this:
class Base {};
class Derived : public Base {};
int main() {
Base *b = new Derived;
}
In this case, b has a static type of Base *, but a dynamic type of Derived * (because it was declared as a pointer to a Base, but is actually pointing at an instance of Derived).
So, if you want to recover an actual dynamic type, you'll need to start by defining some base class, and some derived class(es), and convert between them. When/if you do that, you usually want to use dynamic_cast rather than reinterpret_cast to do the job (it'll automatically check the actual type, so the cast will fail if you try to cast to a type that it's not really pointing at). But in most cases, you want to define some sort of virtual function in the base class, and override it as needed in the derived classes, so you don't need to use dynamic_cast at all. Also note that dynamic_cast only works on classes that contain at least one virtual function (but if you're using public inheritance without any virtual functions, you're probably doing something wrong).
Alternatively, you can create basically a discriminated union. You'll need to store something to record what actual type is stored, and you'll use that to cast back to the correct when needed.
enum type { FLOAT, DOUBLE };
struct value {
type t;
void *value;
};
float f = 1.2f
double d = 3.2;
value v { FLOAT, &f };
value y { DOUBLE, &d };
void do_call(value v) {
if (v.type == FLOAT) {
use_float(*reinterpret_cast<float *>(v.value));
else if (v.type == DOUBLE)
use_double(*reinterpret_cast<double *>(v.value));
}
The compiler, however, won't store anything in a void * to keep track of what type of object it's really pointing at. If you want to cast back from void * to float or double as applicable, you're going to have to store something to keep track of which type that actually was.
Rather than the latter, you might also want to look into using std::variant, which handles storing the type tag automatically, and can help automate most of the type dispatching as well (e.g., with std::visit). At least as typically used, this will act more like an actual tagged union though, so it stores the actual values, rather than pointers to values that are stored elsewhere.
I created a vector that stores any type of value (int, bool, string, &, object,...). I can store stuff, but i have no idea how to get an specific element ([index]). EDIT: (without adding the type)
I haven't tried many things because i have no clue. The only tecnic i can think of is dynamic_cast, but since is a template makes no sense.
#include <vector>
#include <iostream>
struct slot {
virtual void print() = 0;
};
template<typename kind>
struct item : public slot {
kind value;
item(kind value) : value{ value } {};
void print()override { std::cout << value<<std::endl; }
};
class Bag {
std::vector<slot*> backpack;
public:
template<typename kind>
void append(kind stuff) {
backpack.push_back(new item<kind>(stuff));
}
void print_to_test() {
for (slot* it : backpack) { it->print(); }
}
//kind get()...How do i get an item value?
};
Bag bag;
bag.append(1);
bag.append(true);
bag.append("Hola");
bag.append(1232131);
void* a = nullptr;
bag.append(a);
bag.print_to_test();
//works fine, prints everything
//but can't get an specific value, like bag[index]
The dynamic cast will work. Note that it requires at least one virtual method - a destructor can be used if nothing else.
Yes, there isn't a way how can you reliably retrieve the value. C++ doesn't have a general object base as other languages nor any useful runtime reflection.
What you've implemented is known as type erasure and is actually used in e.g. std::function or std::any.
You should not use raw pointers and new for ownership. Use std::unique_ptr instead. Also since you only refer to the objects through the base class you need the virtual destructor. Otherwise, you won't be able to delete them correctly, again one more reason for std::unique_ptr as it deletes the pointer by itself.
If you want to get the value, what would you do with it? To quote Bjarne Stroustrup:
There is no useful universal class: a truly universal carries no semantics of its own.
Yes, you can store this value in std::any, but that's it, what would you want to do with it? Print it? Well, in that case it's no longer any but printable as in your example, so either use templates or virtual methods to express these traits in the types of the stored objects.
Consider using std::variant for known set of possible types and prefer std::any to owning void*. If you need the latter rethink your design choices first.
As others pointed out, dynamic_cast will work fine (as long as the caller knows what type is in the specific index) :
item<int>& someInt = dynamic_cast<item<int>&>(*bag.backpack[0]);
std::cout << "someInt: ";
someInt.print();
Note: You didn't provide accessor to backpack member, so I assumed it's public
Output:
someInt: 1
I hope the headline isn't too confusing. What I have is a class StorageManager containing a list of objects of classes derived from Storage. Here is an example.
struct Storage {}; // abstract
class StorageManager
{
private:
map<string, unique_ptr<Storage>> List; // store all types of storage
public:
template <typename T>
void Add(string Name) // add new storage with name
{
List.insert(make_pair(Name, unique_ptr<Storage>(new T())));
}
Storage* Get(string Name) // get storage by name
{
return List[Name].get();
}
};
Say Position is a special storage type.
struct Position : public Storage
{
int X;
int Y;
};
Thanks to the great answers on my last question the Add function already works. What I want to improve is the Get function. It reasonable returns a pointer Storage* what I can use like the following.
int main()
{
StorageManager Manager;
Manager.Add<Position>("pos"); // add a new storage of type position
auto Strge = Manager.Get("pos"); // get pointer to base class storage
auto Pstn = (Position*)Strge; // convert pointer to derived class position
Pstn->X = 5;
Pstn->Y = 42;
}
It there a way to get rid of this pointer casting by automatically returning a pointer to the derived class? Maybe using templates?
use:
template< class T >
T* Get(std::string const& name)
{
auto i = List.find(name);
return i == List.end() ? nullptr : static_cast<T*>(i->second.get());
}
And then in your code:
Position* p = Manager.Get<Position>("pos");
I don't see what you can do for your Get member function besides what #BigBoss already pointed out, but you can improve your Add member to return the used storage.
template <typename T>
T* Add(string Name) // add new storage with name
{
T* t = new T();
List.insert(make_pair(Name, unique_ptr<Storage>(t)));
return t;
}
// create the pointer directly in a unique_ptr
template <typename T>
T* Add(string Name) // add new storage with name
{
std::unique_ptr<T> x{new T{}};
T* t = x.get();
List.insert(make_pair(Name, std::move(x)));
return t;
}
EDIT The temporary prevents us from having to dynamic_cast.
EDIT2 Implement MatthieuM's suggestion.
You can also further improve the function by accepting a value of the
type to be inserted, with a default argument, but that might incur an
additional copy.
When you have a pointer or reference to an object of some class, all you know is that the actual runtime object it references is either of that class or of some derived class. auto cannot know the runtime type of an object at compile time, because the piece of code containing the auto variable could be in a function that is run twice -- once handling an object of one runtime type, another handling an object with a different runtime type! The type system can't tell you what exact types are in play in a language with polymorphism -- it can only provide some constraints.
If you know that the runtime type of an object is some particular derived class (as in your example), you can (and must) use a cast. (It's considered preferable to use a cast of the form static_cast<Position*>, since casts are dangerous, and this makes it easier to search for casts in your code.)
But generally speaking, doing this a lot is a sign of poor design. The purpose of declaring a base class and deriving other class types from it is to enable objects of all of these those types to be treated the same way, without casting to a particular type.
If you want to always have the correct derived type at compile time without ever using casts, you have no choice but to use a separate collection of that type. In this case, there is probably no point deriving Position from Storage.
If you can rearrange things so that everything that a caller of StorageManager::Get() needs to do with a Position can be done by calling functions that don't specify Position-specific information (such as co-ordinates), you can make these functions into virtual functions in Storage, and implement Position-specific versions of them in Position. For example, you could make a function Storage::Dump() which writes its object to stdout. Position::Dump() would output X and Y, while the implementations of Dump() for other conceivable derived classes would output different information.
Sometimes you need to be able to work with an object that could be one of several essentially unrelated types. I suspect that may be the case here. In that case, boost::variant<> is a good way to go. This library provides a powerful mechanism called the Visitor pattern, which allows you to specify what action should be taken for each of the types that a variant object could possibly be.
Apart from the fact that this looks like a terrible idea... let's see what we can do to improve the situation.
=> It's a bad idea to require default construction
template <typename T>
T& add(std::string const& name, std::unique_ptr<T> element) {
T& t = *element;
auto result = map.insert(std::make_pair(name, std::move(element)));
if (result.second == false) {
// FIXME: somehow add the name here, for easier diagnosis
throw std::runtime_error("Duplicate element");
}
return t;
}
=> It's a bad idea to downcast blindly
template <typename T>
T* get(std::string const& name) const {
auto it = map.find(name);
return it != map.end() ? dynamic_cast<T*>(it->second.get()) : nullptr;
}
But frankly, this system is quite full of holes. And probably unnecessary in the first place. I encourage you to review the general problem an come up with a much better design.
I would like to define a completely generic mapping in c++ where I can map anything to anything.
I tried std::map but what should K and V be to make it general enough so I can map primitives or objects (as keys) to other primitives or objects (as values).
Or is there another mechanism I could use?
EDIT: For clarification, I am trying to define a relationship in the base class (from which all my classes are derived) that will allow me to attach arbitrary data to my classes. The simplest approach would be a be a name-value pair, where the above key is a string. I was wondering if i do something more generic?
Impossible- as it should be. Such a mapping would be worthless, since you can't depend on any meaningful behaviour of either key or value, and it's impossible to design either a binary relation or hash function that would be meaningful across "anything", or that could operate on any type, so it's nowhere near even the realm of possible.
Edit: There is nothing preventing std::unordered_map<std::string, boost::any>- or indeed, boost::any which happens to hold a std::unordered_map of some types.
However, your design appears highly questionable. You're basically completely subverting the compiler for no apparent benefit. Why would you derive every class from a common base? And why on earth would you want to attach arbitrary data? The usual way to put data in a class is to put it in the class, not blow all your safety and performance and sanity by trying to coerce C++ into being an interpreted language.
It is possible - so in this point I disagree with #DeadMG.
It is worthless - in this point full agreement,
However I do not understand that concept of answering, I mean "don't do it" answers instead "it can be done in this way, but my advise is don't do it". I do not pretend to be "life teacher" - I am just answering,
For values - use something like boost::any.
For keys - it is more complicated - because std::map defines order in keys. So generic keys must follow thess rules:
If real keys types are the same - use order from the real keys
If real keys are not the same - you must define order between types (like order of typeinfo::name())
Generic keys must be copy constructible
Let see my proposal for keys (using type erasure):
template <typename T>
struct GenKeyTypeOrder;
class GenKeyImplInt {
public:
// true if before other Key in other
virtual bool before(const GenKeyImplInt&) const = 0;
// type value
virtual int typeOrder() const = 0;
virtual GenKeyImplInt* clone() const = 0;
virtual ~GenKeyImplInt() {}
};
template <typename RealKey>
class GenKeyImpl : public GenKeyImplInt {
public:
GenKeyImpl(RealKey realKey) : realKey(realKey) {}
// true if before other Key in other
virtual bool before(const GenKeyImplInt& r) const
{
const GenKeyImpl* rp = dynamic_cast<const GenKeyImpl*>(&r);
if (rp) return realKey < rp->realKey;
return typeOrder() < r.typeOrder();
}
// type value
virtual int typeOrder() const { return GenKeyTypeOrder<RealKey>::VALUE; }
virtual GenKeyImpl* clone() const { return new GenKeyImpl(*this); }
private:
RealKey realKey;
};
class GenKey {
public:
// true if before other Key in other
friend bool operator < (const GenKey& l, const GenKey& r)
{
return l.impl->before(*r.impl);
}
template <typename T>
GenKey(T t) : impl(new GenKeyImpl<T>(t)) {}
GenKey(const GenKey& oth) : impl(oth.impl->clone()) {}
~GenKey() { delete impl; }
private:
GenKey& operator = (const GenKey& oth); // not defined
GenKeyImplInt* impl;
};
// define for every type you want be used as generic key
template <>
struct GenKeyTypeOrder<int> { enum { VALUE = 0 }; };
template <>
struct GenKeyTypeOrder<std::string> { enum { VALUE = 1 }; };
Full example at ideone
See also this article
You will need to make K and V be special objects.
The object will need to include what object type it is.
struct {
void *pointer;
string type;
// int type; // this is also possible
} Object;
The above Object can point to anything. However, it also needs something to say what type it is, hence the type string.
Then you need to be able to cast the pointer back to the required type, by reading what is in type.
Eg.
if (type == "int") cout << (int*)(myobject.pointer) << endl;
Anyways, if you do something like this, you are almost starting to build a loosely-typed interpreter, because for any operation you want to do with the object, you will need to check its type (whether you are adding, concatenating or printing the value to stdout).
It is probably better if you use a class object, and use inheritance to store any data you need.
class Object {
public virtual string to_string() {
return "";
}
};
Then if you want to store an integer:
class Integer : public Object {
int i;
public string to_string() {
char str[50];
sprintf(str,"%d",i);
return string(str);
}
public Integer operator=(int a) {
i=a;
return this;
}
};
This way you can define an interface of all the functions you want all objects to support.
Note that making the base Object class have virtual functions means that if you say:
Integer a;
a=5;
Object object = (Object)a;
cout << object.to_string << endl; // prints "5"
So that the function called is that defined by the actual (true) type of the object.
Is it possible to store a type name as a C++ variable? For example, like this:
type my_type = int; // or string, or Foo, or any other type
void* data = ...;
my_type* a = (my_type*) data;
I know that 99.9% of the time there's a better way to do what you want without resorting to casting void pointers, but I'm curious if C++ allows this sort of thing.
No, this is not possible in C++.
The RTTI typeid operator allows you to get some information about types at runtime: you can get the type's name and check whether it is equal to another type, but that's about it.
Not as written, but you could do something similar...
class Type
{
public:
virtual ~Type(){}
virtual void* allocate()const=0;
virtual void* cast(void* obj)const=0;
};
template<typename T> class TypeImpl : public Type
{
public:
virtual void* allocate()const{ return new T; }
virtual void* cast(void* obj)const{ return static_cast<T*>(obj); }
};
// ...
Type* type = new TypeImpl<int>;
void* myint = type->allocate();
// ...
This kind of thing can be extended depending on what features you need.
You can't do that in C++, but you can use the boost any library then test for the type it holds. Example:
bool is_int(const boost::any & operand)
{
return operand.type() == typeid(int);
}
http://www.boost.org/doc/libs/1_42_0/doc/html/any/s02.html
No you can't store the type directly as you want, but you can instead store the name of the type.
const char* str = typeid(int).name();
I guess whenever you planned to use that variable for comparison, you could instead at that time compare the str variable against the name() of the types.
const char* myType = typeid(int).name();
//....
//Some time later:
if(!strcmp(myType, typeid(int).name()))
{
//Do something
}
More info available here
Yes, if you code it yourself.
enum Foo_Type{
AFOO,
B_AFOO,
C_AFOO,
RUN
};
struct MyFoo{
Foo_Type m_type;
Boost::shared_ptr<Foo> m_foo;
}
as commented below, what I left out was that all these "foo" types would have to be related to Foo. Foo would, in essence, be your interface.
Today I had a similar problem while coding:
I had the need to store a polymoriphic data type (here named refobj) over wich call functions of the concrete classes implementing it. I need a solution that doesn't cast the variable explicitly because I need to reduce the amount of code.
My solution (but I haven't tested it yet) looks similar to a previous answer. Actually is quite an experimental solution. It look like this...
// interface to use in the function
class Type
{
public:
virtual void* getObj()const=0;
};
// here the static_cast with the "stored" type
template<typename T> class TypeImpl : public Type
{
public:
TypeImpl(T *obj) {myobj=obj;}
virtual void* getObj()const{ return static_cast<T*>(myobj); }
private:
T* myobj;
};
// here the type that will contain the polimorific type
// that I don't want to cast explicitly in my code
Type *refobj;
// here the "user code "
void userofTypes()
{
( refobj->getObj() ).c_str();
// getObj() should return a string type over which
// calling string concrete functions ...let's try!
}
void main()
{
refobj=new TypeImpl < string > ( new string("hello") );
userofTypes();
}
// it might seem absurd don't cast refobj explicitly, but of
// course there are situation in which it can be useful!
Types are not objects in C++ (where they are in Ruby, for instance), so you cannot store instances of a type. Actually, types never appear in the executing code (RTTI is just extra storage).
Based on your example, it looks like you're looking for typedefs.
typedef int Number;
Number one = 1;
Number* best = (Number*) one;
Note that a typedef isn't storing the type; it is aliasing the type.
A better process is to have a common base class containing a load method, and an interface for loaders. This would allow other parts of the program to load data generically without knowledge of the descendant class:
struct Load_Interface;
struct Loader
{
virtual void visit(Load_Interface&) = 0;
}
struct Load_Interface
{
virtual void accept_loader(Loader& l)
{
l.visit(*this);
}
};
This design avoids the need to know the types of objects.