Friday, April 10, 2015

Digest for comp.lang.c++@googlegroups.com - 25 updates in 5 topics

"Norman J. Goldstein" <normvcr@telus.net>: Apr 09 09:34PM -0700

Aside from writing virtual methods to do the job, I am wondering whether
there is something like type_index/type_info to divulge the (void*)
address of the most derived type. On a related question, when
restricting to single inheritance, are compilers obliged to have the
same (void*) address for each class in the hierarchy?
Paavo Helde <myfirstname@osa.pri.ee>: Apr 10 12:05AM -0500

"Norman J. Goldstein" <normvcr@telus.net> wrote in news:mg7jt9$b2e$1
 
> Aside from writing virtual methods to do the job, I am wondering whether
> there is something like type_index/type_info to divulge the (void*)
> address of the most derived type.
 
As far as I understand you have a pointer to a base class and want to get a
pointer to the most derived class, without knowing the most derived class
type? That would be
 
dynamic_cast<void*>(...)
 
(assuming you have polymorphic types so dynamic_cast can be used). This
works for multiple inheritance as well.
 
> On a related question, when
> restricting to single inheritance, are compilers obliged to have the
> same (void*) address for each class in the hierarchy?
 
I believe this is not guaranteed, but will probably work in practice with
most compilers, at least when all classes are of the same type (polymorphic
or not polymorphic).
 
hth
Paavo
"Öö Tiib" <ootiib@hot.ee>: Apr 10 12:48AM -0700

On Friday, 10 April 2015 07:35:00 UTC+3, Norman J. Goldstein wrote:
> Aside from writing virtual methods to do the job, I am wondering whether
> there is something like type_index/type_info to divulge the (void*)
> address of the most derived type.
 
You must have pointer to non-virtual base class to find out most
derived type with 'typeid(*ptr)'; 'void' is not base class. If you
know exactly from pointer to what type you did cast implicitly or
with 'static_cast' to 'void*' then you can 'static_cast' it back.
If you 'dynamic_cast<void*>' then you get address of most
non-virtually derived object, that is actually not what you want
unless you exactly know the type.
 
> On a related question, when
> restricting to single inheritance, are compilers obliged to have the
> same (void*) address for each class in the hierarchy?
 
On case of single *and* non-virtual inheritance such classes in practice
usually have same address but it is not guaranteed. The practice is
because of required order of initialization and required implicit casts
and finding vtable location (existence of what is not guaranteed at all)
are likely cheaper to implement. On case of virtual inheritance the
address is not same usually. Virtual inheritance is most expensive and
tricky. Introducing it into language was likely mistake, but I don't
care since I never use it. On case of multiple inheritance the different
base subobjects can not be at same address by simple logic.
 
Generally it is better to avoid casting. If you really need to then
consider making some special functions or member functions that do
it. It is easier to instrument such function with debug checks and
breakpoints.
"Norman J. Goldstein" <normvcr@telus.net>: Apr 10 01:15AM -0700

I wrote a test routine, and it does exactly as you say.
Many thanks.
 
On 04/09/2015 10:05 PM, Paavo Helde wrote:
>> there is something like type_index/type_info to divulge the (void*)
>> address of the most derived type.
 
> As far as I understand you have a pointer to a base class and want to
get a
"Norman J. Goldstein" <normvcr@telus.net>: Apr 10 01:30AM -0700

On 04/10/2015 12:48 AM, Öö Tiib wrote:
> If you 'dynamic_cast<void*>' then you get address of most
> non-virtually derived object, that is actually not what you want
> unless you exactly know the type.
 
On gcc 4.8, the dynamic_cast<void*> is doing the right thing, whether
the most derived object is virtually derived, or not (according to my
test routine). Why do you think virtual derivation could make a difference?
"Öö Tiib" <ootiib@hot.ee>: Apr 10 01:59AM -0700

On Friday, 10 April 2015 11:30:21 UTC+3, Norman J. Goldstein wrote:
 
> On gcc 4.8, the dynamic_cast<void*> is doing the right thing, whether
> the most derived object is virtually derived, or not (according to my
> test routine). Why do you think virtual derivation could make a difference?
 
Sorry, I read it over and I did remember/know it incorrectly.
 
'dynamic_cast'ing from virtual base pointer to most derived type pointer
and 'dynamic_cast'ing from virtual base pointer to 'void*' must give same
address. That is address of most derived object.
 
Avoiding a feature because of its inefficiency and avoiding other feature
because of its fragility apparently may result with misremembering how
those overlap.
"Norman J. Goldstein" <normvcr@telus.net>: Apr 10 09:53AM -0700

On 04/10/2015 01:59 AM, Öö Tiib wrote:
 
> Avoiding a feature because of its inefficiency and avoiding other feature
> because of its fragility apparently may result with misremembering how
> those overlap.
 
Thanks for checking!
Paavo Helde <myfirstname@osa.pri.ee>: Apr 10 02:06PM -0500

嘱 Tiib <ootiib@hot.ee> wrote in
 
> Avoiding a feature because of its inefficiency and avoiding other
> feature because of its fragility apparently may result with
> misremembering how those overlap.
 
Inefficiency is always relative. There are lots of usage cases where the
speed is not so critical. For example I have used dynamic_cast quite
successfully in some MFC-based projects (working around MFC design
deficiences via multiple derivation and dynamic_casting between my and MFC
class hierarchy trees). Worked pretty well actually, at least when compared
to the rest of the MFC mess.
 
Cheers
Paavo
ram@zedat.fu-berlin.de (Stefan Ram): Apr 10 02:20PM

>>>>(Below, I use »N« for an end-of-line symbol in the source code.)
 
#include<iostream.h>N#include<bitset.h>Nint x;main(){bitset<16>a[]={21845,13107,3855,255};while(x<4)cout<<a[x++]<<"\n";}
#include<iostream>Nint main(){std::cout<<"0101010101010101\n0011001100110011\n0000111100001111\n0000000011111111\n";}
#include<iostream>Nint main(){for(int i=0;i<4;++i){for(int j=0;j<16;++j)std::cout<<j/(1<<i)%2;std::cout<<'\n';}}
#include<stdio.h>Nint main(){for(int i=0;i<4;++i){for(int j=0;j<16;++j)putchar('0'+j/(1<<i)%2);puts("");}}
#include<stdio.h>Nint main(){int i,j;for(i=0;i<4;++i,puts(""))for(j=0;j<16;++j)putchar('0'+j/(1<<i)%2);}
#include<stdio.h>Nint main(){int i=0,j;for(;i<4;++i,puts(""))for(j=0;j<16;++j)putchar('0'+j/(1<<i)%2);}
 
(Nonportably, »'0'« might be replaced by »48«, and often »stdio.h« can be replaced by »cstdio«.)
ram@zedat.fu-berlin.de (Stefan Ram): Apr 10 02:33PM

>>>>>(Below, I use »N« for an end-of-line symbol in the source code.)
 
#include<iostream.h>N#include<bitset.h>Nint x;main(){bitset<16>a[]={21845,13107,3855,255};while(x<4)cout<<a[x++]<<"\n";}
#include<iostream>Nint main(){std::cout<<"0101010101010101\n0011001100110011\n0000111100001111\n0000000011111111\n";}
#include<iostream>Nint main(){for(int i=0;i<4;++i){for(int j=0;j<16;++j)std::cout<<j/(1<<i)%2;std::cout<<'\n';}}
#include<stdio.h>Nint main(){for(int i=0;i<4;++i){for(int j=0;j<16;++j)putchar('0'+j/(1<<i)%2);puts("");}}
#include<stdio.h>Nint main(){int i,j;for(i=0;i<4;++i,puts(""))for(j=0;j<16;++j)putchar('0'+j/(1<<i)%2);}
#include<stdio.h>Nint main(){int i=0,j;for(;i<4;++i,puts(""))for(j=0;j<16;++j)putchar('0'+j/(1<<i)%2);}
#include<stdio.h>Nint main(){int i=0,j;for(;i<4;++i,puts(""))for(j=0;j<16;)putchar('0'+j++/(1<<i)%2);}
 
(Nonportably, »'0'« might be replaced by »48«, and often »stdio.h« can be replaced by »cstdio«.)
ram@zedat.fu-berlin.de (Stefan Ram): Apr 10 02:40PM

>If you're going to be pedantic, assuming '1' equals '0'+1 isn't portable
>either.
 
»In both the source and execution basic character sets,
the value of each character after 0 in the above list of
decimal digits shall be one greater than the value of
the previous.« - 2.3p3
ram@zedat.fu-berlin.de (Stefan Ram): Apr 10 07:05PM

>>>>>>(Below, I use »N« for an end-of-line symbol in the source code.)
 
#include<iostream.h>N#include<bitset.h>Nint x;main(){bitset<16>a[]={21845,13107,3855,255};while(x<4)cout<<a[x++]<<"\n";}
#include<iostream>Nint main(){std::cout<<"0101010101010101\n0011001100110011\n0000111100001111\n0000000011111111\n";}
#include<iostream>Nint main(){for(int i=0;i<4;++i){for(int j=0;j<16;++j)std::cout<<j/(1<<i)%2;std::cout<<'\n';}}
#include<stdio.h>Nint main(){for(int i=0;i<4;++i){for(int j=0;j<16;++j)putchar('0'+j/(1<<i)%2);puts("");}}
#include<stdio.h>Nint main(){int i,j;for(i=0;i<4;++i,puts(""))for(j=0;j<16;++j)putchar('0'+j/(1<<i)%2);}
#include<stdio.h>Nint main(){int i=0,j;for(;i<4;++i,puts(""))for(j=0;j<16;++j)putchar('0'+j/(1<<i)%2);}
#include<stdio.h>Nint main(){int i=0,j;for(;i<4;++i,puts(""))for(j=0;j<16;)putchar('0'+j++/(1<<i)%2);}
#include<stdio.h>Nint main(){for(int i=0;i<64;i%16?0:puts(""))putchar('0'+i++/(1<<(i>>4))%2);}
 
(Nonportably, »'0'« might be replaced by »48«, and often »stdio.h« can be replaced by »cstdio«.)
Martin Shobe <martin.shobe@yahoo.com>: Apr 09 06:37PM -0500

On 4/9/2015 3:54 PM, Vir Campestris wrote:
 
>> Not a valid C++ program.
 
> Not valid - or just not compatible with any OS I ever came across?
 
> (Win and *n?x seem to require argc and argv...)
 
Not valid. There are several things, including a type for x and a
prototype for printf, that need to be fixed before we talk about the
non-standard prototype for main.
 
Martin Shobe
"Lőrinczy Zsigmond" <nospam@for.me>: Apr 10 06:29AM +0200

> main(x){printf("%x",x);}
> Is a valid C++ program
> and what number it print...
 
Never hesitate to try it.
http://www.thefreecountry.com/compilers/cpp.shtml
scott@slp53.sl.home (Scott Lurndal): Apr 10 01:50PM


>> Not a valid C++ program.
 
>Not valid - or just not compatible with any OS I ever came across?
 
>(Win and *n?x seem to require argc and argv...)
 
*n?x provides argc, argv, envp and auxv. Most programs
only use argc, argv, and some use envp as well. There is
nothing illegal or undefined about defining main to consume
only the argc parameter; the remaining parameters passed by
the exec call will be ignored and unavailable to the app
(although getenv()/setenv()/putenv() will access the environment
directly). auxv, which is passed from the kernel,
is often consumed by the run-time-linker/loader and may or may
not be provided to the application depending on the OS.
 
As otherwise pointed out, the value of the 'argc' parameter
depends on how the main function was invoked.
 
scott
Robert Wessel <robertwessel2@yahoo.com>: Apr 10 01:34PM -0500

On Fri, 10 Apr 2015 13:50:18 GMT, scott@slp53.sl.home (Scott Lurndal)
wrote:
 
>directly). auxv, which is passed from the kernel,
>is often consumed by the run-time-linker/loader and may or may
>not be provided to the application depending on the OS.
 
 
There's' nothing preventing an implementation from providing an
extension so that a form of main() other than the two specified in the
standard are supported, but the form being proposed here is undefined
per the standard. Yes, with some of the common calling conventions
used by C implementations it would work naturally, but that is
certainly not required.
ram@zedat.fu-berlin.de (Stefan Ram): Apr 10 01:59PM

>ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>>(Below, I use »N« for an end-of-line symbol in the source code.)
 
#include<iostream.h>N#include<bitset.h>Nint x;main(){bitset<16>a[]={21845,13107,3855,255};while(x<4)cout<<a[x++]<<"\n";}
#include<iostream>Nint main(){std::cout<<"0101010101010101\n0011001100110011\n0000111100001111\n0000000011111111\n";}
#include<iostream>Nint main(){for(int i=0;i<4;++i){for(int j=0;j<16;++j)std::cout<<j/(1<<i)%2;std::cout<<'\n';}}
#include<stdio.h>Nint main(){for(int i=0;i<4;++i){for(int j=0;j<16;++j)putchar('0'+j/(1<<i)%2);puts("");}}
#include<stdio.h>Nint main(){int i,j;for(i=0;i<4;++i,puts(""))for(j=0;j<16;++j)putchar('0'+j/(1<<i)%2);}
 
(Nonportably, »'0'« might be replaced by »48, and often »stdio.h« can be replaced by »cstdio«.)
Martijn van Buul <pino@dohd.org>: Apr 10 02:36PM

* Stefan Ram:
> i=0,j;for(;i<4;++i,puts(""))for(j=0;j<16;++j)putchar('0'+j/(1<<i)%2);}
 
> (Nonportably, »'0'« might be replaced by »48«, and often »stdio.h« can be
> replaced by »cstdio«.)
 
If you're going to be pedantic, assuming '1' equals '0'+1 isn't portable
either.
 
--
Martijn van Buul - pino@dohd.org
Victor Bazarov <v.bazarov@comcast.invalid>: Apr 10 10:43AM -0400

On 4/10/2015 10:36 AM, Martijn van Buul wrote:
>> replaced by »cstdio«.)
 
> If you're going to be pedantic, assuming '1' equals '0'+1 isn't portable
> either.
 
Yes, it most certainly is. See [lex.charset]/3, "...In both the source
and execution basic character sets, the value of each character after 0
in the above list of decimal digits shall be one greater than the value
of the previous. "
 
In my understanding it means that '1' == '0' + 1, and so on.
 
V
--
I do not respond to top-posted replies, please don't ask
JiiPee <no@notvalid.com>: Apr 10 04:10PM +0100

On 10/04/2015 15:43, Victor Bazarov wrote:
> the value of the previous. "
 
> In my understanding it means that '1' == '0' + 1, and so on.
 
> V
 
yes thats my understanding as well. I remember reading from somewhere
that is it a rule.
scott@slp53.sl.home (Scott Lurndal): Apr 10 03:11PM

>> replaced by »cstdio«.)
 
>If you're going to be pedantic, assuming '1' equals '0'+1 isn't portable
>either.
 
Although it works in all of the BCD, EBCDIC, UTF-8 (ASCII subset) and USASCII codesets.
Luca Risolia <luca.risolia@linux-projects.org>: Apr 10 05:35PM +0200

On 10/04/2015 16:33, Stefan Ram wrote:
> #include<stdio.h>Nint main(){int i,j;for(i=0;i<4;++i,puts(""))for(j=0;j<16;++j)putchar('0'+j/(1<<i)%2);}
> #include<stdio.h>Nint main(){int i=0,j;for(;i<4;++i,puts(""))for(j=0;j<16;++j)putchar('0'+j/(1<<i)%2);}
> #include<stdio.h>Nint main(){int i=0,j;for(;i<4;++i,puts(""))for(j=0;j<16;)putchar('0'+j++/(1<<i)%2);}
 
maybe short, as required, but not really interesting in C++. Try to
produce the whole result in a generic way at compile time instead ;)
Marcel Mueller <news.5.maazl@spamgourmet.org>: Apr 10 06:16PM +0200

On 10.04.15 16.33, Stefan Ram wrote:
>>>>>> (Below, I use »N« for an end-of-line symbol in the source code.)
 
> #include<iostream.h>N#include<bitset.h>Nint x;main(){bitset<16>a[]={21845,13107,3855,255};while(x<4)cout<<a[x++]<<"\n";}
> #include<stdio.h>Nint main(){int i=0,j;for(;i<4;++i,puts(""))for(j=0;j<16;)putchar('0'+j++/(1<<i)%2);}
#include<stdio.h>Nint main(){int
i=4,j;for(;i--;puts(""))for(j=16;j--;putchar('1'-(j>>3-i)%2));}
#include<stdio.h>Nint
main(){printf("%016b\n%016b\n%016b\n%016b\n",21845,13107,3855,255);}
 
But %b is AFAIK not part of the standard.
 
 
Marcel
asetofsymbols@gmail.com: Apr 10 11:32AM -0700

int i,r;main(k){for(;k<16;r%16?0:(puts(""),k=i))for(i=0;i<2*k;++i,++r)putchar('1'-(i<k));}
Victor Bazarov <v.bazarov@comcast.invalid>: Apr 10 09:16AM -0400

On 4/9/2015 6:44 PM, Doug Mika wrote:
> duckBilledP.Mammal::Animal::Age=25;
> //duckBilledP.Animal::Age=25; //why wouldn't this work?
> }
 
Actually, given the hierarchy the simple
 
duckBilledP.Age = 25;
 
ought to do. However, if somewhere in the derived classes there were a
member 'Age', the scope resolution would help avoiding ambiguity, IIRC.
 
V
--
I do not respond to top-posted replies, please don't ask
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: