Reputation: 825
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
Upvotes: 0
Views: 184
Reputation: 45424
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.
Upvotes: 0
Reputation: 2827
You can have a pointer to any type (object, pointer, primitive type etc.) but you can not have a pointer to a reference.
Upvotes: 0
Reputation: 1663
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;
....
}
Upvotes: 1
Reputation: 275385
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.
Upvotes: 8
Reputation: 129364
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; }
}
Upvotes: 4
Reputation: 264381
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.
Upvotes: 0
Reputation: 272487
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...
Upvotes: 1