CRTP with reinterpret_cast into target class - c++

Background
I'd like facades to be applied on ad-hoc basis, and not baking them into the class itself. But I need to operate on the data, so I need this to be accessible from the facade. Here is a small example:
#include <array>
#include <iostream>
template <typename T>
struct x_getter
{
friend T;
double x() const
{
return (*real_self)[0];
}
void x(double new_x)
{
(*real_self)[0] = new_x;
}
private:
T* real_self = reinterpret_cast<T*>(this);
x_getter() = default; //prevents accidental creation
};
struct coordinates : std::array<double, 3>, x_getter<coordinates>
{
using std::array<double, 3>::array;
};
int main()
{
coordinates origin{};
std::cout << origin.x();
origin.x(12.7);
std::cout << ' ' << origin.x() << '\n';
}
It segfaults. Using something similar a while back, I got unlucky to be able to get away with it.
Question
How do I make this with type of target class be available in facade class?
My understanding of class layout
Somewhere inside of the object, in unordered manner, there are array and x_getter. By reinterpret_casting it, I'm trying to trick it to think that this is coordinates, but when it performs operator[], the offset which is used is a bit off, which goes outside of the object, thus segfaulting.

The problem here is that reinterpret_cast does not work because this pointer does not point at the beginning of coordinates class since it inherits from array before inheriting from x_getter. The memory layout for this class looks like this:
coordinates
|- std::array<double, 3>
|- x_getter
When you use reinterpret_cast<T*>(this) the address stored in this pointer is the address of x_getter object, but you force compiler to assume that it is actually an address of coordinates object. So dereferencing such a pointer to derived class leads to all kinds of undefined behavior.
Typically CRTP should use static_cast inside of method:
double x() const
{
return (*static_cast<TDerived const *>(this))[0];
}
Unlike reinterpret_cast, static_cast will properly adjust this pointer to correctly point at derived object.

Related

Resizing local containers in const method through base class with template specialisations

I want to create instances of a class and, depending on the type, provide a resize functionality, which is only applicable to containers that provide such functionality (for simplicity, lets assume its just a vector). The resizing is done in a base class as I have several classes that have a common base but all requiring the same functionality.
The following code demonstrates the current problem
#include <iostream>
#include <vector>
class base {
public:
template<typename T>
void resize(T &var, T &resizer) {
var.resize(resizer.size());
std::cout << "resized a vector" << std::endl;
}
void resize(double &var, double &resizer) {
std::cout << "just a double, no resizing done" << std::endl;
}
};
template<typename T>
class child1 : public base {
public:
void doOperation() const {
T a, b;
// assume here that b has actually a different size from a
this->resize(a, b);
}
};
template<typename T>
class child2 : public base {
public:
void wildlyDifferentOperation() const {
T c, d;
// assume here that d has actually a different size from c
this->resize(c, d);
}
};
int main() {
child1<std::vector<double>> obj1;
obj1.doOperation();
child2<std::vector<int>> obj2;
obj2.wildlyDifferentOperation();
child1<double> obj3;
obj3.doOperation();
return 0;
}
As shown here, I used template specializations to catch types that can not be resized (and I know that it will always be a double) and I use a templated version for the containers that can be resized, as I don't know ahead which types I actually need (i.e. it could be std::vector<int>, std::vector<double> etc...).
Of course, if I remove const from the doOperation() method then the code works as expected but with the const I get an error saying error: passing ‘const child1<std::vector<double> >’ as ‘this’ argument discards qualifiers [-fpermissive] which is not surprising (and I get a similar message for child2 and wildlyDifferentOperation()).
My question now is how can I use the code above to make it work? I though I could maybe const_cast the arguments in this->resize or use mutable and then declare T a as class member variables to no avail.
Any suggestions are welcome but I would like the following to remain the same:
void doOperation() and wildlyDifferentOperation() should remain const
I want to be able to create local variables as T a inside doOperation() and wildlyDifferentOperation() and pass those to a separate method where they get resized if they are a container. To make things simpler, I know that I will either get a double or a container, but I don't want to impose any restriction on the template arguments of the container (i.e. accept std::vector, std::vector and so forth)
I need to be able to use the same functionality to resize my containers from other child classes that derive from the base class.
If there is a cleaner solution not requiring template specializations that would also be acceptable. It should, however, work with a C++14 conform compiler.
Make base::resize either static or const. Without knowing the semantics of what you're going for here, I would guess const.

Iterating through objects with a common base class in contigious memory

I'm trying to figure out how I can iterate through a container (like std::vector) of objects that share a common base parent class contiguously in memory.
To demonstrate the problem let's use the following examples.
class Base
{
public:
Base();
virtual void doStuff() = 0;
};
class DerivedA : public Base
{
private:
//specific A member variables
public:
DerivedA();
virtual void doStuff();
};
class DerivedB : public Base
{
private:
//specific B member variables
public:
DerivedB();
virtual void doStuff();
};
Now, using std::vector to iterate would keep the objects in contiguous memory but we would experience slicing as there isn't room for the derived properties.
So we have to use polymorphic technique using pointers like so
int main ()
{
std::vector<Base*> container;
container.push_back(new DerivedA());
container.push_back(new DerivedB());
for (std::vector<Base*>::iterator i = container.begin(); i!=container.end(); i++)
{
(*(*i)).doStuff();
}
}
As far as I know that should work fine given that the classes are implemented.
Problem:
Now, the vector contains pointers in contiguous memory but that does not mean that the addresses they are pointing to are.
So if I want to be able to delete and insert objects into the vector on the fly at any time, the objects will be spread all over the place in memory.
Question:
It seems like everyone suggests doing it the std::vector way but why isn't it considered problematic that it isn't iterable contiguously in memory (assuming we actually use the pointer)?
Am I forced to do it the copy-pasta way?
int main ()
{
std::vector<DerivedA> containerA;
DerivedA a;
containerA.push_back(a);
std::vector<DerivedB> containerB;
DerivedB b;
containerB.push_back(b);
for (std::vector<DerivedA>::iterator i = containerA.begin(); i!=container.end(); i++)
{
(*i).doStuff();
}
for (std::vector<DerivedB>::iterator i = containerB.begin(); i!=container.end(); i++)
{
(*i).doStuff();
}
}
I'm guessing there might not be a real solution to this since keeping objects of various sizes linearly in memory doesn't really make sense but if anyone can give me some advice I'd appreciate it.
Let's take the questions in order.
Q: How I can create a contiguous, heterogeneous container?
A: You can't.
Suppose you used some
placement new
shenanigans to arrange your objects in memory like this:
[B ][DA ][DB ][B ][B ][DB ][DA ]
How would the iteration mechanism know how far to advance the iteration
pointer from one object to the next? The number of bytes from the first
element to the second is different from the second to the third.
The reason contiguous arrays have to be homogenous is so the distance
from one object to the next is the same for all elements. You might
try to embed a size in each object, but then you basically have a linked
list rather than an array (albeit one with good
locality).
This reasoning leads to the idea to use an array of pointers, about which
you have posed the next question:
Q: Why isn't it considered problematic that it isn't iterable contiguously
A: It is not as slow as you think.
Your concern seems to be the performance of following pointers to
scattered memory locations. But the cost of following these pointers is
unlikely to be dominant. Don't get hung up on micro-optimizations like
memory layout until you have solid evidence they are needed.
Q: Am I forced to do it the copy-pasta way?
A: No!
Here, the concern seems to be maintainability rather than performance.
Maintainability is much more important in my opinion, and a good thing
to think about early.
For maintainability, you already have a fine solution: maintain a
vector of Base*.
If you really want to use multiple vectors, there is still a better way
than copy and paste: use a template function, like this (untested):
template <class T>
void doStuffToVector(std::vector<T> &vec)
{
for (std::vector<T>::iterator i = vec.begin(); i!=vec.end(); ++i) {
(*i).doStuff();
}
}
Then call it on each container:
doStuffToVector(containerA);
doStuffToVector(containerB);
If your only concern is maintainability, either the vector of pointers
or the template function should suffice.
Q: Any advice?
A: For starters, ignore performance, at least as far as constant
factors are concerned. Concentrate on correctness and maintainability.
Then, measure performance. Observe that this question did not begin
with a statement of current and desired speed. You don't yet have an
actual problem to solve!
After measurement, if you conclude it's too slow, use a
profiler
to find out where the slow spots are. They are almost never where you
think they will be.
Case in point: this entire question and answers have been focused on
the iteration, but no one has raised the point that the virtual function
calls to doStuff are much more likely to be the bottleneck! Virtual
function calls are expensive because they are indirect control flow,
which causes major problems for the
pipeline;
indirect data access is much less expensive because the
data cache is usually very
effective at satisfying data access requests quickly.
Q: (Implied) How would I optimize this?
A: After careful measurement, you might possibly find that this code
(the iteration itself, including virtual function dispatch; not what's
inside doStuff) is a bottleneck. That must mean it's being executed
for billions of iterations, minimum.
First, look into algorithmic improvements that will reduce the number
of iterations required.
Next, eliminate the virtual function call, for example by embedding an
explicit indicator of object type and testing it with if or switch.
That will allow the processor's
branch predictor to
be much more effective.
Finally, yes, you'd probably want to put all of the elements into one
contiguous array to improve locality and eliminate the indirect data
access. That will mean eliminating the class hierarchy too so all
objects are the same type, either combining all of the fields into a
single class and/or using a union. This will harm your program's
maintainability! That is sometimes one of the costs of writing high
performance code, but is actually necessary only very rarely.
A very simple solution is to sort your pointer array by address value. Then if you iterate your vector, they will be in memory order. Perhaps not contiguous, but in order nonetheless, which reduces cache misses.
The only way to truly have contiguous memory is to allocate it as such, for example have vectors of objects of derived type stored in their own container, which you then reference in your pointer vector.
It seems like everyone suggests doing it the std::vector way but why
isn't it considered problematic that it isn't iterable contiguously in
memory (assuming we actually use the pointer)?
I don't know who considers it problematic or not. As in the other answers, in a lot of cases you just don't care. Do the profiling and you'll see if you have to optimize it or not.
In most of the cases, people would recomment you to use a std::vector<std::unique_ptr<...>>.
In many cases though, it is very important to have your objects in contiguous memory. Gaming is one of those cases. I write a lot of computational code (finite element libraries), where it is also very important. You could read about how to organize your data in a different way in order to have everything line up. For instance, it might be interesting to store all Arm objects in a std::vector rather than store each Arm in a Hero object and access the Arm objects through the Hero object.
Anyways, here is an easy way to store your objects from your example in a contiguous container.
For the base class, use alignas to fix the size of the object. Make sure it's big enough so all derived objects fit in it. In my below example, DerivedA has size 16, DerivedB has size 24. The specified align size must be a power of 2, so we choose 32.
struct alignas(32) Base
{
virtual void print() const {}
};
struct DerivedA : Base
{
void print() const final override { std::cout << "num: " << i << std::endl; }
int i = 1;
};
struct DerivedB : Base
{
void print() const final override { std::cout << "num: " << i << std::endl; }
int i = 2;
double j = 100.0;
};
Now we can write instances of DerivedA and DerivedB with placement new:
int main ()
{
std::vector<Base> v(2);
new (&v[0]) DerivedA();
new (&v[1]) DerivedB();
for (const auto& e : v)
e.print();
return 0;
}
EDIT
The problem here is that you need to manage the sizes manually. Also, as has been pointed out to me recently, alignas is designed for positioning the object in memory, not to allocate size. Maybe a better way would just be using std::variant.
int main()
{
std::vector<std::variant<DerivedA, DerivedB>> vec;
vec.emplace_back(DerivedA());
vec.emplace_back(DerivedB());
for (const auto& e : vec)
std::visit(VisitPackage(), e);
return 0;
}
where VisitPackage could be something like this:
struct VisitPackage
{
void operator()(const DerivedA& d) { d.print(); }
void operator()(const DerivedB& d) { d.print(); }
};
Below is a full and short example of how to get what you want using std::variant.
#include <iostream>
#include <vector>
#include <variant>
struct Base { virtual void print() const = 0; };
struct DerivedA : Base { void print() const final override { std::cout << "DerivedA\n"; } };
struct DerivedB : Base { void print() const final override { std::cout << "DerivedB\n"; } };
struct Print
{
template <typename T>
// note that the operator() calls print from DerivedA or DerivedB directly
void operator()(const T& obj) const { obj.print(); }
};
int main ()
{
using var_t = std::variant<DerivedA, DerivedB>;
std::vector<var_t> vec { DerivedA(), DerivedB() };
for (auto& e : vec)
std::visit(Print(), e);
return 0;
}
If we have to store objects in array, their type must be fixed. Then we have these variants:
allocate dynamically and store pointers - if pointed objects are required to be continuous in memory, use custom allocator
use polymorphic type of a fixed size, e.g. union, as a storage type
For the second variant, the code could be something like this:
#include <new>
struct A {
A() {}
virtual void f() {}
};
struct B : A {
B() {}
void f() override {}
};
union U {
A a;
B b;
U() {}
};
int main() {
U u[2];
new (&u[0]) A;
new (&u[1]) B;
((A*)&u[0])->f(); // A::f
((A*)&u[1])->f(); // B::f
}
std::vector<T> iterators assume that the objects in the contiguous memory are of type T, std::vector<T>::iterator::operator++ considers sizeof T to be invariant - that is, it doesn't consult the specific instance for size data.
In essence, you can think of vector and vector::iterator as a thin facade over a T* m_data pointer, such that iterator++ is really just a basic pointer operation.
You will likely need to use a custom allocator and in-place new to prepare your data, accompanied by either indexing, linking etc. Perhaps consider something like http://www.boost.org/doc/libs/1_58_0/doc/html/intrusive/slist.html
See also boost::stable_vector
std::vector allocateS the objects in continuous memory but the object pointers you are storing within the vector are not. This is how you iterate through vector. Following code is written in c++14. The problem described is not solvable by this solution as the object pointers are stored in continuous memory but not the actual objects.
#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>
using namespace std;
class Base
{
public:
Base() {}
virtual void doStuff() = 0;
};
class DerivedA : public Base
{
private:
//specific A member variables
public:
DerivedA() : Base() {}
virtual void doStuff() {
std::cout << "Derived Class A - Do Stuff" << std::endl;
}
};
class DerivedB : public Base
{
private:
//specific B member variables
public:
DerivedB() : Base() {}
virtual void doStuff() {
std::cout << "Derived Class B - Do Stuff" << std::endl;
}
};
int main() {
// your code goes here
std::vector<std::unique_ptr<Base> > container;
container.push_back(std::make_unique<DerivedA>());
container.push_back(std::make_unique<DerivedB>());
std::for_each(container.begin(), container.end(),[](std::unique_ptr<Base> & b) {
b->doStuff();
});
return 0;
}
Live Demo here.

C++ One std::vector containing template class of multiple types

I need to store multiple types of a template class in a single vector.
Eg, for:
template <typename T>
class templateClass{
bool someFunction();
};
I need one vector that will store all of:
templateClass<int> t1;
templateClass<char> t2;
templateClass<std::string> t3;
etc
As far as I know this is not possible, if it is could someone say how?
If it isn't possible could someone explain how to make the following work?
As a work around I tried to use a base, non template class and inherit the template class from it.
class templateInterface{
virtual bool someFunction() = 0;
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction();
};
I then created a vector to store the base "templateInterface" class:
std::vector<templateInterface> v;
templateClass<int> t;
v.push_back(t);
This produced the following error:
error: cannot allocate an object of abstract type 'templateInterface'
note: because the following virtual functions are pure within 'templateInterface'
note: virtual bool templateInterface::someFunction()
To fix this error I made the function in templateInterface not a pure virtual by providing a function body, this compiled but when calling the function the overide is not used, but instead the body in the virtual function.
Eg:
class templateInterface{
virtual bool someFunction() {return true;}
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction() {return false;}
};
std::vector<templateInterface> v;
templateClass<int> i;
v.push_back(i);
v[0].someFunction(); //This returns true, and does not use the code in the 'templateClass' function body
Is there any way to fix this so that the overridden function is used, or is there another workaround to store multiple template types in a single vector?
Why your code doesn't work:
Calling a virtual function on a value doesn't use polymorphism. It calls the function which is defined for the type of this exact symbol as seen by the compiler, not the runtime type. When you insert sub types into a vector of the base type, your values will be converted into the base type ("type slicing"), which is not what you want. Calling functions on them will now call the function as defined for the base type, since not it is of that type.
How to fix this?
The same problem can be reproduced with this code snippet:
templateInterface x = templateClass<int>(); // Type slicing takes place!
x.someFunction(); // -> templateInterface::someFunction() is called!
Polymorphism only works on a pointer or reference type. It will then use the runtime type of the object behind the pointer / reference to decide which implementation to call (by using it's vtable).
Converting pointers is totally "safe" with regard to type slicing. Your actual values won't be converted at all and polymorphism will work as expected.
Example, analogous to the code snippet above:
templateInterface *x = new templateClass<int>(); // No type slicing takes place
x->someFunction(); // -> templateClass<int>::someFunction() is called!
delete x; // Don't forget to destroy your objects.
What about vectors?
So you have to adopt these changes in your code. You can simply store pointers to actual types in the vector, instead of storing the values directly.
When working with pointers you also have to care about deleting your allocated objects. For this you can use smart pointers which care about deletion automatically. unique_ptr is one such smart pointer type. It deletes the pointee whenever it goes out of scope ("unique ownership" - the scope being the owner). Assuming the lifetime of your objects is bound to the scope this is what you should use:
std::vector<std::unique_ptr<templateInterface>> v;
templateClass<int> *i = new templateClass<int>(); // create new object
v.push_back(std::unique_ptr<templateInterface>(i)); // put it in the vector
v.emplace_back(new templateClass<int>()); // "direct" alternative
Then, call a virtual function on one of these elements with the following syntax:
v[0]->someFunction();
Make sure you make all functions virtual which should be possible to be overridden by subclasses. Otherwise their overridden version will not be called. But since you already introduced an "interface", I'm sure you are working with abstract functions.
Alternative approaches:
Alternative ways to do what you want is to use a variant type in the vector. There are some implementations of variant types, the Boost.Variant being a very popular one. This approach is especially nice if you don't have a type hierarchy (for example when you store primitive types). You would then use a vector type like std::vector<boost::variant<int, char, bool>>
Polymorphism only works through pointers or references. You'll
need the non-template base. Beyond that, you'll need to decide
where the actual objects in container will live. If they're all
static objects (with sufficient lifetime), just using
a std::vector<TemplateInterface*>, and inserting with
v.push_back(&t1);, etc., should do the trick. Otherwise,
you'll probably want to support cloning, and keep clones in the
vector: preferably with Boost pointer containers, but
std::shared_ptr can be used as well.
The solutions given so far are fine though be aware that in case you were returning the template type other than bool in your example , none of these would help as the vtable slots would not be able to be measured before hand. There are actually limits , from a design point of view , for using a template oriented polymorphic solution.
Solution nr. 1
This solution inspired by Sean Parent's C++ Seasoning talk. I highly recommend to check it out on youtube. My solution simplified a bit and the key is to store object in method itself.
One method only
Create a class that will invoke method of stored object.
struct object {
template <class T>
object(T t)
: someFunction([t = std::move(t)]() { return t.someFunction(); })
{ }
std::function<bool()> someFunction;
};
Then use it like this
std::vector<object> v;
// Add classes that has 'bool someFunction()' method
v.emplace_back(someClass());
v.emplace_back(someOtherClass());
// Test our vector
for (auto& x : v)
std::cout << x.someFunction() << std::endl;
Several methods
For several methods use shared pointer to share object between methods
struct object {
template <class T>
object(T&& t) {
auto ptr = std::make_shared<std::remove_reference_t<T>>(std::forward<T>(t));
someFunction = [ptr]() { return ptr->someFunction(); };
someOtherFunction = [ptr](int x) { ptr->someOtherFunction(x); };
}
std::function<bool()> someFunction;
std::function<void(int)> someOtherFunction;
};
Other types
Primitive types (such as int, float, const char*) or classes (std::string etc.) may be wrapped in the same way as object class do but behave differently. For example:
struct otherType {
template <class T>
otherType(T t)
: someFunction([t = std::move(t)]() {
// Return something different
return true;
})
{ }
std::function<bool()> someFunction;
};
So now it is possible to add types that does not have someFunction method.
v.emplace_back(otherType(17)); // Adding an int
v.emplace_back(otherType("test")); // A string
Solution nr. 2
After some thoughts what we basically done in first solution is created array of callable functions. So why not just do the following instead.
// Example class with method we want to put in array
struct myclass {
void draw() const {
std::cout << "myclass" << std::endl;
}
};
// All other type's behaviour
template <class T>
void draw(const T& x) {
std::cout << typeid(T).name() << ": " << x << std::endl;
}
int main()
{
myclass x;
int y = 17;
std::vector<std::function<void()>> v;
v.emplace_back(std::bind(&myclass::draw, &x));
v.emplace_back(std::bind(draw<int>, y));
for (auto& fn : v)
fn();
}
Conclusion
Solution nr. 1 is definitely an interesting method that does not require inheritance nor virtual functions. And can be used to other stuff where you need to store a template argument to be used later.
Solution nr. 2, on the other hand, is simpler, more flexible and probably a better choice here.
If you're looking at a container to store multiple types, then you should explore boost variant from the popular boost library.

Are pointers to any kind of variables possible?

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.

C++: pointer to struct in struct definition questions

Considering that piece of code:
struct myStruct
{
myStruct *next;
};
Next is a pointer of struct declared in the struct definition, right?
What's the utility of - next - ? How can I use it?
Seems like it's an implementation of a linked-list.
You can use next if you want to chain such structures together to traverse them later. Of course, having other members in myStruct would make more sense.
example:
struct myStruct
{
int data;
myStruct *next;
};
myStruct st_1;
myStruct st_2;
st_1.data = 1;
st_2.data = 2;
st_1.next = &st_2; //st_1.next->data is now 2
The utility of this pointer is whatever you implement in myStruct. You can hold a direct relationship to other myStruct structs (through the pointer) using this pointer and directly manipulate them (i.e. like "knowing" about other objects).
For instance (note that for all intents and purposes, struct's in C++ are public classes),
class Test
{
public:
doSomethingToTheOtherStruct() {
if(t != NULL)
t->touch();
setTouched(bool touch) {
touched = touch;
}
setT(Test* other) {
t = other;
}
bool isTouched() const {
return touched;
}
private:
Test* t;
bool touched;
};
This class has some very simple methods which can demonstrate the power of using pointers. Now an example using it is below.
#include <iostream>
using namespace std;
int main()
{
Test t1;
Test t2;
Test* t3 = new Test;
// Notice that we set the pointers of each struct to point to a different one
// This is not necessary, but is definitely more useful than setting it to itself
// since you already have the "this" pointer in a class.
t1->setT(&t2);
t2->setT(t3);
t3->setT(&t1);
cout<< t1.isTouched() << t2.isTouched() << t3->isTouched() << endl;
t1->doSomethingToTheOtherStruct();
t2.doSomethingToTheOtherStruct();
cout<< t1.isTouched() << t2.isTouched() << t3->isTouched() << endl;
delete t3;
return 0;
}
Take note in the results of this code. t1 is never set to touched, but inadvertently (through the pointers), t2 and t3 become "touched."
The fact it is a pointer to the same class and that the member variable is called "next" suggests it is a linked list, as others have pointed out.
If the variable was a pointer to the same class but called "parent" it would most likely be some kind of parent/child relationship. (For example GUI widgets that have a parent that is also a widget).
What you might question is why you are allowed to do this: the answer is that pointers to data -types are all the same size, so the compiler will already know how many bytes it needs for this pointer.
For the same reason, you can have in your class (or struct) a pointer to a type for which the data type has only been declared and not defined. (Quite common to do).
That is correct. This kind of nested structs are used in linked lists.