473,722 Members | 2,459 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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_cas t 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_cas t<mem_t>(&entit y::f1_),
reinterpret_cas t<mem_t>(&entit y::f2_),
reinterpret_cas t<mem_t>(&entit y::f3_),
reinterpret_cas t<mem_t>(&entit y::f4_),
};
int main(int, char **)
{
entity e;
for(int i=0; i<4; ++i)
{
printf("%s\n", (e.*(entity::fi elds[i])).foo());
}

return 0;
}
Nov 17 '05 #1
12 1237
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_cas t 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_cas t<mem_t>(&entit y::f1_),
reinterpret_cas t<mem_t>(&entit y::f2_),
reinterpret_cas t<mem_t>(&entit y::f3_),
reinterpret_cas t<mem_t>(&entit y::f4_),
};
int main(int, char **)
{
entity e;
for(int i=0; i<4; ++i)
{
printf("%s\n", (e.*(entity::fi elds[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_cas t 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_pette r" <vl*****@hotmai l.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_cas t.
If I do reinterpret_cas t 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_cas t
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_pette r" <vl*****@hotmai l.com> wrote in message
news:eR******** ******@TK2MSFTN GP11.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_cas t 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_cas t<mem_t>(&entit y::f1_),
reinterpret_cas t<mem_t>(&entit y::f2_),
reinterpret_cas t<mem_t>(&entit y::f3_),
reinterpret_cas t<mem_t>(&entit y::f4_),
};
int main(int, char **)
{
entity e;
for(int i=0; i<4; ++i)
{
printf("%s\n", (e.*(entity::fi elds[i])).foo());
}

return 0;
}

Nov 17 '05 #5
"Alexander Grigoriev" <al***@earthlin k.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_cas t.


Now I see. Thanks.
>> If I do reinterpret_cas t 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_cas t
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_cas t 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.********@com Acast.net> wrote in message
news:eM******** ******@tk2msftn gp13.phx.gbl...
"Alexander Grigoriev" <al***@earthlin k.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.********@com Acast.net> wrote in message
news:eM******** ******@tk2msftn gp13.phx.gbl...
"Alexander Grigoriev" <al***@earthlin k.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.********@com Acast.net> wrote in message
news:uN******** ******@TK2MSFTN GP09.phx.gbl...
Alexander Grigoriev wrote:
"Victor Bazarov" <v.********@com Acast.net> wrote in message
news:eM******** ******@tk2msftn gp13.phx.gbl...
"Alexander Grigoriev" <al***@earthlin k.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_cas t.
Nov 17 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
12204
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
5003
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 signature. When developing this lib, I figured that the pointer-to-member-function, although seemingly an attractive solution, does not work well for us.
7
1478
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 legal... Thanks, Dave struct D;
6
2624
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
1484
by: cbull | last post by:
class A { }; class B: public A { void f(); }; typedef void (A::*MPA)(void); MPA mpA;
2
4419
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;*/}; class C: public B {public : C(){}/*friend class T;*/}; struct T { A* newA() {return new C();}}; int main() {}
1
3966
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 arguments, is this VC specific or a standard c++ behavior? the code looks like this: class Base { public: int member; };
7
3813
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
4657
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
8867
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8740
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9386
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9158
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9090
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8059
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, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6685
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 presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4503
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
3
2148
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.