473,406 Members | 2,549 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 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 1221
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Bren | last post by:
Hi all, Given this situation: class Base { typedef void (Base::*FN_FOO)(); virtual void Foo() = 0; // pure virtual void GetFoo(FN_FOO pfnFoo) = 0; // pure virtual
37
by: Ben | last post by:
Hi, there. Recently I was working on a problem where we want to save generic closures in a data structure (a vector). The closure should work for any data type and any method with pre-defined...
7
by: Dave | last post by:
Hello all, In the code below, I use a pointer to an object under construction. Is the usage below legal? I have come across similar code at work. It compiles, but I'm not sure it's really...
6
by: marco_segurini | last post by:
Hi, the following sample code shows a compiler error I get trying to build some old code with the last CL compiler (vers 13.10.3077): //----- begin #include <iostream> namespace ns {
6
by: cbull | last post by:
class A { }; class B: public A { void f(); }; typedef void (A::*MPA)(void); MPA mpA;
2
by: Steven T. Hatton | last post by:
Can somebody explain why making T a friend of either B or C will permit the code to compile? class A{ protected: A(){} }; class T; class B: protected A {protected: B(){}/*friend class T;*/};...
1
by: autumn | last post by:
Hi everybody, I'm having problem passing pointer to member object as template argument, seems VC 2005 does not allow 'pointer to base member' to 'pointer to derived member' conversion in template...
7
by: WaterWalk | last post by:
Hello. I thought I understood member function pointers, but in fact I don't. Consider the following example: class Base { public: virtual ~Base() {} }; class Derived : public Base {
5
by: Tim Frink | last post by:
Hi, I'm experimenting with function pointers and found two questions. Let's assume this code: 1 #include <iostream> 2 class A; 3 4 //////////////////////////////////////////// 5 class B
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.