471,092 Members | 1,035 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,092 software developers and data experts.

pointer to member conversion to a pointer to member that is a member's base class

Dear All,

There is the problem in nutshells (see the program bellow):

It is ok to convert pointer to F<T> to the pointer to I.
Now if I have pointer to member "F<T> entity::*" can I convert it to the "I
entity::*"?
Compiler does not let me to do that (I've tried on VC 7.1 and Comeau 4.3.3).
If I do reinterpret_cast then the program will be compiled and runs as
expected all though I would like to know possible implications of this
approach.

The goal here to create a static array of fields for a class and be able to
execute algorithms on this array (like the for loop in the main function).

Thanks,
Vladimir.

#include <string>

using namespace std;

struct I
{
virtual char const * foo()=0;
};

template <typename T>
struct F : public I
{
char const * foo()
{
return typeid(T).name();
}

T v_;
};

struct entity
{
typedef I entity::* mem_t;

static mem_t fields[4];

F<int> f1_;
F<char> f2_;
F<string> f3_;
F<double> f4_;
};

entity::mem_t entity::fields[4] = {
reinterpret_cast<mem_t>(&entity::f1_),
reinterpret_cast<mem_t>(&entity::f2_),
reinterpret_cast<mem_t>(&entity::f3_),
reinterpret_cast<mem_t>(&entity::f4_),
};
int main(int, char **)
{
entity e;
for(int i=0; i<4; ++i)
{
printf("%s\n", (e.*(entity::fields[i])).foo());
}

return 0;
}
Nov 17 '05 #1
12 1109
Vladimir_petter wrote:
There is the problem in nutshells (see the program bellow):

It is ok to convert pointer to F<T> to the pointer to I.
Yes, I is an unambiguous and accessible base class to F<T>.
Now if I have pointer to member "F<T> entity::*" can I convert it to the "I
entity::*"?
Not implicitly, no.
Compiler does not let me to do that (I've tried on VC 7.1 and Comeau 4.3.3).
That's right. In the current Standard no such conversion exist.
If I do reinterpret_cast then the program will be compiled and runs as
expected all though I would like to know possible implications of this
approach.
As the language is defined now, your program causes undefined behaviour.
It might even work as expected (and apparently it does). But it might not
or it might do something really bad, like format your hard drive.

If I were you, I'd present my case to comp.std.c++ and asked for the
addition to the language: a pointer to a member of T of type D should be
convertible to a pointer to a member of T of type B if B is an unambiguous
and accessible base of D. It is a logical extension to 4.10/3.

In C++ terms: {D cv T::*} should be convertible to {B cv T::*} and
{D cv T::&} should be convertible to {B cv T::&} (which
is implied because all pointer conversions are applicable to references
with the exception that there are no null references)
The goal here to create a static array of fields for a class and be able to
execute algorithms on this array (like the for loop in the main function).
Sounds good.

Thanks,
Vladimir.

#include <string>

using namespace std;

struct I
{
virtual char const * foo()=0;
};

template <typename T>
struct F : public I
{
char const * foo()
{
return typeid(T).name();
}

T v_;
};

struct entity
{
typedef I entity::* mem_t;

static mem_t fields[4];

F<int> f1_;
F<char> f2_;
F<string> f3_;
F<double> f4_;
};

entity::mem_t entity::fields[4] = {
reinterpret_cast<mem_t>(&entity::f1_),
reinterpret_cast<mem_t>(&entity::f2_),
reinterpret_cast<mem_t>(&entity::f3_),
reinterpret_cast<mem_t>(&entity::f4_),
};
int main(int, char **)
{
entity e;
for(int i=0; i<4; ++i)
{
printf("%s\n", (e.*(entity::fields[i])).foo());
}

return 0;
}


Victor
Nov 17 '05 #2
Hello Viktor,

I apriciate your response.
Compiler does not let me to do that (I've tried on VC 7.1 and Comeau
4.3.3).
That's right. In the current Standard no such conversion exist.


Could you point me to a paragraph in the standard that would clearly state
this?
I was looking in the 4.11, 5.2.9/9, 5.3.1/2, 8.3/3. None of them clearly
states that
this is invalid.
If I do reinterpret_cast then the program will be compiled and runs as
expected all though I would like to know possible implications of this
approach.


As the language is defined now, your program causes undefined behaviour.
It might even work as expected (and apparently it does). But it might not
or it might do something really bad, like format your hard drive.

If I were you, I'd present my case to comp.std.c++ and asked for the
addition to the language: a pointer to a member of T of type D should be
convertible to a pointer to a member of T of type B if B is an unambiguous
and accessible base of D. It is a logical extension to 4.10/3.


Well I think I'll do that. Unfortunately it would not help to solve my
current problem :-(.

In C++ terms: {D cv T::*} should be convertible to {B cv T::*} and
{D cv T::&} should be convertible to {B cv T::&} (which
is implied because all pointer conversions are applicable to references
with the exception that there are no null references)
I agree with everithing you said above except that I think there is no such
a think as
a reference to a member (see 8.3.2/3).
The goal here to create a static array of fields for a class and be able
to execute algorithms on this array (like the for loop in the main
function).


Sounds good.


But yet unreachable :-(.

Thanks,
Vladimir.

Nov 17 '05 #3
"Vladimir_petter" <vl*****@hotmail.com> wrote...
Hello Viktor,

I apriciate your response.
Compiler does not let me to do that (I've tried on VC 7.1 and Comeau
4.3.3).
That's right. In the current Standard no such conversion exist.


Could you point me to a paragraph in the standard that would clearly state
this?


How can I point you to the paragraph that doesn't exist? See the entire
Clause 4, if you can't find it, it doesn't exist. Clause 4 contains _all_
conversions there are.
I was looking in the 4.11, 5.2.9/9, 5.3.1/2, 8.3/3. None of them clearly
states that
this is invalid.
The Standard is organized in a peculiar way. If certain things are not
explicitly allowed, they are prohibited. That includes conversions. If
there is no operation that is explicitly allowed in 5.2.10, it is not
allowed even with a reinterpret_cast.
If I do reinterpret_cast then the program will be compiled and runs as
expected all though I would like to know possible implications of this
approach.
As the language is defined now, your program causes undefined behaviour.
It might even work as expected (and apparently it does). But it might not
or it might do something really bad, like format your hard drive.

If I were you, I'd present my case to comp.std.c++ and asked for the
addition to the language: a pointer to a member of T of type D should be
convertible to a pointer to a member of T of type B if B is an unambiguous and accessible base of D. It is a logical extension to 4.10/3.


Well I think I'll do that. Unfortunately it would not help to solve my
current problem :-(.


No, but it probably will ensure that when time comes to port it elsewhere
you will have a working solution. Meanwhile enjoy your reinterpret_cast
solution while it "works".

In C++ terms: {D cv T::*} should be convertible to {B cv T::*} and
{D cv T::&} should be convertible to {B cv T::&} (which
is implied because all pointer conversions are applicable to references
with the exception that there are no null references)
I agree with everithing you said above except that I think there is no

such a think as
a reference to a member (see 8.3.2/3).


Well, OK, but perhaps there should be. :-)
The goal here to create a static array of fields for a class and be able to execute algorithms on this array (like the for loop in the main
function).


Sounds good.


But yet unreachable :-(.


I am not sure I understand. Didn't you indicate in your original post
that your code works as you want it?

V
Nov 17 '05 #4
Use static_cast. It allows for those explicit convertions, if the original
and target types are compatible.
"Vladimir_petter" <vl*****@hotmail.com> wrote in message
news:eR**************@TK2MSFTNGP11.phx.gbl...
Dear All,

There is the problem in nutshells (see the program bellow):

It is ok to convert pointer to F<T> to the pointer to I.
Now if I have pointer to member "F<T> entity::*" can I convert it to the "I entity::*"?
Compiler does not let me to do that (I've tried on VC 7.1 and Comeau 4.3.3). If I do reinterpret_cast then the program will be compiled and runs as
expected all though I would like to know possible implications of this
approach.

The goal here to create a static array of fields for a class and be able to execute algorithms on this array (like the for loop in the main function).

Thanks,
Vladimir.

#include <string>

using namespace std;

struct I
{
virtual char const * foo()=0;
};

template <typename T>
struct F : public I
{
char const * foo()
{
return typeid(T).name();
}

T v_;
};

struct entity
{
typedef I entity::* mem_t;

static mem_t fields[4];

F<int> f1_;
F<char> f2_;
F<string> f3_;
F<double> f4_;
};

entity::mem_t entity::fields[4] = {
reinterpret_cast<mem_t>(&entity::f1_),
reinterpret_cast<mem_t>(&entity::f2_),
reinterpret_cast<mem_t>(&entity::f3_),
reinterpret_cast<mem_t>(&entity::f4_),
};
int main(int, char **)
{
entity e;
for(int i=0; i<4; ++i)
{
printf("%s\n", (e.*(entity::fields[i])).foo());
}

return 0;
}

Nov 17 '05 #5
"Alexander Grigoriev" <al***@earthlink.net> wrote...
Use static_cast. It allows for those explicit convertions, if the original
and target types are compatible.
Are they compatible? How do you define "compatible"?
[...]

Nov 17 '05 #6
Hello Viktor,

How can I point you to the paragraph that doesn't exist? See the entire
Clause 4, if you can't find it, it doesn't exist. Clause 4 contains _all_
conversions there are.
I was looking in the 4.11, 5.2.9/9, 5.3.1/2, 8.3/3. None of them clearly
states that
this is invalid.


The Standard is organized in a peculiar way. If certain things are not
explicitly allowed, they are prohibited. That includes conversions. If
there is no operation that is explicitly allowed in 5.2.10, it is not
allowed even with a reinterpret_cast.


Now I see. Thanks.
>> If I do reinterpret_cast then the program will be compiled and runs as
>> expected all though I would like to know possible implications of this
>> approach.
>
> As the language is defined now, your program causes undefined
> behaviour.
> It might even work as expected (and apparently it does). But it might not > or it might do something really bad, like format your hard drive.
>
> If I were you, I'd present my case to comp.std.c++ and asked for the
> addition to the language: a pointer to a member of T of type D should
> be
> convertible to a pointer to a member of T of type B if B is an unambiguous > and accessible base of D. It is a logical extension to 4.10/3.


Well I think I'll do that. Unfortunately it would not help to solve my
current problem :-(.


No, but it probably will ensure that when time comes to port it elsewhere
you will have a working solution. Meanwhile enjoy your reinterpret_cast
solution while it "works".
>
> In C++ terms: {D cv T::*} should be convertible to {B cv T::*} and
> {D cv T::&} should be convertible to {B cv T::&} (which
> is implied because all pointer conversions are applicable to references
> with the exception that there are no null references)


I agree with everithing you said above except that I think there is no

such
a think as
a reference to a member (see 8.3.2/3).


Well, OK, but perhaps there should be. :-)
>> The goal here to create a static array of fields for a class and be able >> to execute algorithms on this array (like the for loop in the main
>> function).
>
> Sounds good.


But yet unreachable :-(.


I am not sure I understand. Didn't you indicate in your original post
that your code works as you want it?


What I've meant was that compiler does not guarantee that this mechanism
will work. So I can do that only on my own risk and in that case I should
clearly understand in which cases it will work and in which cases it would
not. Now after making some experiments and reading this article:
http://www.codeproject.com/cpp/FastD...asp#xx876855xx
I think that reinterpret_cast solution will work only if "I" (see program in
the first post) is not virtually inherited the very base class (first in
hierarchy) of "F<T>", which is true in my case. But for safety I will
provide a way to verify this during compilation and issue an error if this
invariant is broken.

Thanks,
Vladimir
Nov 17 '05 #7

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:eM**************@tk2msftngp13.phx.gbl...
"Alexander Grigoriev" <al***@earthlink.net> wrote...
Use static_cast. It allows for those explicit convertions, if the original and target types are compatible.


Are they compatible? How do you define "compatible"?


If there exists static_cast from B* to D * and vice versa (B being base
class of D), then there exist both implicit conversion from pointer to
member of base B to pointer to member of derived D (4.11/2) and explicit
static_cast to another direction (5.2.9/9).
Nov 17 '05 #8
Alexander Grigoriev wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:eM**************@tk2msftngp13.phx.gbl...
"Alexander Grigoriev" <al***@earthlink.net> wrote...
Use static_cast. It allows for those explicit convertions, if the
original
and target types are compatible.


Are they compatible? How do you define "compatible"?

If there exists static_cast from B* to D * and vice versa (B being base
class of D), then there exist both implicit conversion from pointer to
member of base B to pointer to member of derived D (4.11/2) and explicit
static_cast to another direction (5.2.9/9).


Did you miss the fact that it's not a member of B or member of D the OP
was asking about? They both are members of 'T', but one is of class B
and the other is of class D. B T::* and D T::*. Can we simply drop the
fact that they are pointers to members of the same type? I submit that
we cannot.

Victor
Nov 17 '05 #9

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:uN**************@TK2MSFTNGP09.phx.gbl...
Alexander Grigoriev wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:eM**************@tk2msftngp13.phx.gbl...
"Alexander Grigoriev" <al***@earthlink.net> wrote...

Use static_cast. It allows for those explicit convertions, if the


original
and target types are compatible.

Are they compatible? How do you define "compatible"?

If there exists static_cast from B* to D * and vice versa (B being base
class of D), then there exist both implicit conversion from pointer to
member of base B to pointer to member of derived D (4.11/2) and explicit
static_cast to another direction (5.2.9/9).


Did you miss the fact that it's not a member of B or member of D the OP
was asking about? They both are members of 'T', but one is of class B
and the other is of class D. B T::* and D T::*. Can we simply drop the
fact that they are pointers to members of the same type? I submit that
we cannot.

Victor


Yes, such conversion doesn't seem possible, other than brute-force
reinterpret_cast.
Nov 17 '05 #10
Alexander Grigoriev wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:uN**************@TK2MSFTNGP09.phx.gbl...
Alexander Grigoriev wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:eM**************@tk2msftngp13.phx.gbl...
"Alexander Grigoriev" <al***@earthlink.net> wrote...
>Use static_cast. It allows for those explicit convertions, if the

original
>and target types are compatible.

Are they compatible? How do you define "compatible"?

If there exists static_cast from B* to D * and vice versa (B being base
class of D), then there exist both implicit conversion from pointer to
member of base B to pointer to member of derived D (4.11/2) and explicit
static_cast to another direction (5.2.9/9).


Did you miss the fact that it's not a member of B or member of D the OP
was asking about? They both are members of 'T', but one is of class B
and the other is of class D. B T::* and D T::*. Can we simply drop the
fact that they are pointers to members of the same type? I submit that
we cannot.

Victor

Yes, such conversion doesn't seem possible, other than brute-force
reinterpret_cast.


reinterpret_cast is not the "catch all" method. It still must behave
according to the language rules. The Standard specifies a strict set of
conversions _permitted_ to be done using reinterpret_cast (see 5.2.10)
and this one isn't one of them either. So, "brute force" will result in
_undefined_behaviour_.

I think the language could be changed to permit that conversion (even to
let it be implicit), but it's a issue to be resolved in comp.std.c++.

Victor
Nov 17 '05 #11
Vladimir_petter wrote:
Dear All,

There is the problem in nutshells (see the program bellow):
[..]


I posted your message along with my summary to comp.std.c++. If and
when there are replies, I'll report back here.

Victor
Nov 17 '05 #12

Hello Viktor,
There is the problem in nutshells (see the program bellow):
[..]


I posted your message along with my summary to comp.std.c++. If and
when there are replies, I'll report back here.


Thanks for your efforts. I actually posted my question to the
comp.lang.c++.moderated, but might be I've picked up a wrong group or the
way I put the problem is not right, but so far there was no response.
Anyways I've marked your posting in comp.std.c++ and will monitor it.

Thanks,
Vladimir.
Nov 17 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Bren | last post: by
37 posts views Thread by Ben | last post: by
6 posts views Thread by marco_segurini | last post: by
6 posts views Thread by cbull | last post: by
2 posts views Thread by Steven T. Hatton | last post: by
7 posts views Thread by WaterWalk | last post: by
5 posts views Thread by Tim Frink | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.