A cool thing with C++ is that it lets you create variables of pointer-to-member types. The most common use case seems to be to get a pointer to a method:
struct foo
{
int x() { return 5; }
};
int (foo::*ptr)() = &foo::x;
foo myFoo;
cout << (myFoo.*ptr)() << '\n'; // prints "5"
However, messing around, I realized that they can just as well point to member variables:
struct foo
{
int y;
};
int foo::*ptr = &foo::y;
foo myFoo;
myFoo.*ptr = 5;
cout << myFoo.y << '\n'; // prints "5"
This is pretty rad. It led me to a further experiment: what if you could get a pointer to a sub-member of a structure?
struct foo
{
int y;
};
struct bar
{
foo aFoo;
};
int bar::*foo::*ptr;
This actually compiles.
However, I have no idea how to assign it anything useful. None of the following works:
int bar::*foo::*ptr = &bar::foo::y; // no member named "foo" in "bar"
int bar::*foo::*ptr = &bar::aFoo::y; // no member named "aFoo" in "bar" (??)
int bar::*foo::*ptr = &foo::y; // can't init 'int bar::*foo::*' with 'int foo::*'
Furthermore, according to the error that this generates, it appears that this type is not exactly what I have in mind:
int bar::*foo::*ptr = nullptr;
bar myBar;
myBar.*ptr = 4; // pointer to member type ‘int bar::*’ incompatible
// with object type ‘bar’
It appears that this concept evades me. Obviously, I can't rule out that it simply gets parsed in a way entirely different from what I would expect.
Would anyone please explain me what an int bar::*foo::*
actually is? Why does gcc tell me that a pointer to a member of bar
is incompatible with a bar
object? How would I use an int bar::*foo::*
, and how would I construct a valid one?
int& foo(); is a function returning a reference to int . Your provided function returns int without reference.
The terms foobar (/ˈfuːbɑːr/), foo, bar, baz, and others are used as metasyntactic variables and placeholder names in computer programming or computer-related documentation.
Foo (pronounced FOO) is a term used by programmers as a placeholder for a value that can change, depending on conditions or on information passed to the program. Foo and other words like it are formally known as metasyntactic variables.
It's a generic name for a thing, using in computer science in general. Etymologically, "foo" is the first syllable of "FUBAR", which is an acronym for "**ed Up Beyond All Recognition/Recovery". Follow this answer to receive notifications.
Here's a "valid" way of initializing such a monstrosity:
struct bar;
struct foo
{
int y;
int bar::* whatever;
};
struct bar
{
foo aFoo;
};
int bar::* foo::* ptr = &foo::whatever;
As we can see, ptr
is a pointer to a member of foo
(foo::*
, reading right to left), where that member is itself a pointer to a member of bar
(bar::*
), where that member is an int.
How would I use an int bar::* foo::*
You wouldn't, hopefully! But if you are under duress, try this!
struct bar
{
foo aFoo;
int really;
};
int bar::* foo::* ptr = &foo::whatever;
foo fleh;
fleh.whatever = &bar::really;
bar blah;
blah.*(fleh.*ptr) = 42;
std::cout << blah.really << std::endl;
That would be a pointer to a data member that is itself a pointer to a data member (an int
member of bar
).
Don't ask me what it is actually useful for - my head is spinning a little :)
EDIT: Here's a full example of it in action:
#include <iostream>
struct bar {
int i;
};
struct foo {
int bar::* p;
};
int main()
{
bar b;
b.i = 42;
foo f;
f.p = &bar::i;
int bar::*foo::*ptr = &foo::p;
std::cout << (b.*(f.*ptr));
}
Output is, of course, 42.
It can get even more fun - here's some pointers to member functions that return pointers to member functions:
#include <iostream>
struct bar {
int f_bar(int i) { return i; };
};
struct foo {
int(bar::*f_foo())(int)
{
return &bar::f_bar;
}
};
int main()
{
int(bar::*((foo::*ptr)()))(int) = &foo::f_foo;
bar b;
foo f;
std::cout << (b.*((f.*ptr)()))(42);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With