 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Guest
|
Posted: Fri May 11, 2007 4:46 am Post subject: C++ private/protected hack |
|
|
Hey all. I would like some comments on yet another C++ "hack" that I
have employed in some work I have done (http://www.ischo.com/xrtti).
I had to employ this hack to "work around a limitation of the C++
language. I realize that I am doing something "dangerous" that is not
permitted by the language specification. However, I have a hard time
thinking of how a compiler could make what I am doing *not work*.
Here is the hack:
I needed for some generated code to have access to private members and
methods of a class. So I did the following at the top of my generated
code (before including the header that defines the class in question):
#define private public
#define protected public
// #define class struct
#include "ClassDefinitions.h"
The goal here is to compile my generated code such that it can call
methods of, and reference fields of, classes/structs defined in
ClassDefinitions.h.
Turns out that this works just perfectly, at least using g++. It's as
if every class in ClassDefinitions.h has been laid wide open for my
generated code to manipulate as I need it to.
I know that this is disallowed by the C++ standard - I have read that
specifically the C++ standard says that no macros are ever to be
defined that replace a C++ keyword with a different C++ keyword, or
something like that.
But the thing is - the preprocessor, unless it's be specifically coded
to enforce this C++ rule, will happily replace "private" with "public"
and "protected" with "public" before feeding the resulting code to the
compiler itself. So the compiler will never know that the classes
defined were ever specified with private or protected access. So I
can't see how a compiler, unless via the preprocessor having logic to
specifically disallow what I am doing, could ever *prevent* this hack
from working.
The only danger I can think of is that some compilers might lay out a
class's in-memory representation differently for public fields versus
private or protected fields. If the compiler does the obvious thing
of just considering each field in turn and putting it in sequence in
the class in the order in which they are enumerated in the class
definition, then it doesn't matter what access rights each field is
declared to have. However, there is nothing to prevent a compiler
from putting all public member variables at the "top" of the in-memory
layout of a class and all of the private member variables at the
"bottom" or something like that.
I just can't think of a good reason for a compiler to ever go through
the trouble of implementing extra logic to do this.
Also - if the compiler mangled the names of methods differently for
private methods versus public methods (including, say, the access
rights of the method in the mangled method name) then my technique
would not work for calling methods int he class in question either. I
don't see any reason why it would ever help a compiler to put the
access rights into the mangled name (since access rights cannot be
used in C++ to differentiate between two methods with the same name,
it doesn't help anything to encode these rights in the mangled name),
but I guess a naive or wasteful implementation could do this.
And - you'll notice that I commented out "#define class struct". This
was to try to give access to members of classes that never declared
access rights explicitly and just left the default of private access
on member variables and methods. In this case my #define macros
wouldn't help because they wouldn't change the class at all. But
#define class struct does help because it turns the class into a
struct, which is only different in that it has default public access
to members instead of default private.
The problem is, even though doing so should theoretically have zero
effects on the defined classes/structs, I found that some header files
produced errors when included in this way (notably, some of the C++
STL headers included with the GNU C++ compiler). I didn't investigate
too much to figure out what the actual error was and why it was
happening, I intend to do that later.
First - does anyone have any comments on this technique? I thought of
it myself but then in searching about this problem much later on found
that others have tried it too, and no one has said that it didn't work
for them (although I read something troubling once that seemed to
suggest that some of Microsoft's compilers produce different code
somehow when these macros are invoked - leave it to Microsoft to be
the one to break something that otherwise works for everyone else! -
but I haven't researched this thoroughly either).
Second - if you want to see if this technique works for your compiler,
here is a program to test it:
foo.h:
------------------------------------------------------------
class Foo
{
public:
Foo(int _a, int _b, int _c) : a(_a), b(_b), c(_c) { }
virtual ~Foo() { }
int GetC();
int a;
protected:
int GetCProtected();
int b;
private:
int GetCPrivate();
int c;
};
------------------------------------------------------------
foo.cpp:
------------------------------------------------------------
#include "foo.h"
int Foo::GetC()
{
return this->GetCPrivate();
}
int Foo::GetCProtected()
{
this->GetCPrivate();
}
int Foo::GetCPrivate()
{
return c;
}
------------------------------------------------------------
main.cpp:
------------------------------------------------------------
#include <stdio.h>
#define private public
#define protected public
#include "foo.h"
int main()
{
Foo f(10, 20, 30);
printf("f.a: %d\n", f.a);
printf("f.b: %d\n", f.b);
printf("f.c: %d\n", f.c);
printf("f.GetC(): %d\n", f.GetC());
printf("f.GetCProtected(): %d\n", f.GetCProtected());
printf("f.GetCPrivate(): %d\n", f.GetCPrivate());
return 0;
}
------------------------------------------------------------
Compile foo.cpp and main.cpp into a program and run it. If you get
the following output then this hack works for your compiler:
f.a: 10
f.b: 20
f.c: 30
f.GetC(): 30
f.GetCProtected(): 30
f.GetCPrivate(): 30
I'd be interested in knowing if this does or doesn't work for your
compiler. So far I have tried it only on g++ 4.1.1.
Thanks!
Bryan
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Fri May 11, 2007 9:10 am Post subject: Re: C++ private/protected hack |
|
|
bji-ggcpp (AT) ischo (DOT) com wrote:
| Quote: | I needed for some generated code to have access to private members and
methods of a class.
|
Make it a friend.
| Quote: | So I did the following at the top of my generated
code (before including the header that defines the class in question):
#define private public
#define protected public
|
Doesn't work. Firstly, not everything private is prefixed with 'private:',
you yourself discovered. Secondly, one popular compiler mangles the access
specifier into the linker symbol.
[#define class struct]
| Quote: | The problem is, even though doing so should theoretically have zero
effects on the defined classes/structs, [...]
|
Wrong. The keywork 'class' can also be used in templates, and there it can
replace the keyword 'typename' - 'struct' is not a valid replacement there.
Uli
--
Sator Laser GmbH
Geschäftsführer: Ronald Boers, Amtsgericht Hamburg HR B62 932
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Daniel T. Guest
|
Posted: Sat May 12, 2007 3:04 am Post subject: Re: C++ private/protected hack |
|
|
bji-ggcpp (AT) ischo (DOT) com wrote:
| Quote: | Hey all. I would like some comments on yet another C++ "hack" that I
have employed in some work I have done (http://www.ischo.com/xrtti).
I had to employ this hack to "work around a limitation of the C++
language.
|
I don't see any limitation of the language which this hack would work
around (even if it did work.) Could you be more specific?
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Guest
|
Posted: Sat May 12, 2007 4:27 am Post subject: Re: C++ private/protected hack |
|
|
On May 12, 11:43 am, Daniel Krügler <daniel.krueg...@googlemail.com>
wrote:
| Quote: | On 11 Mai, 22:48, John Moeller <fishc...@gmail.com> wrote:
Actually, I believe that every access section has to have its data in
contiguous memory. But don't quote me on that. (Can anyone
confirm/clarify/correct?)
The essence is given by 9.2/12:
"Nonstatic data members of a (non-union) class declared without an
intervening access-specifier are allocated so that later members have
higher addresses within a class object. The order of allocation of
nonstatic data members separated by an access-specifier is
unspecified (11.1). Implementation alignment requirements might
cause two adjacent members not to be allocated immediately after
each other; so might requirements for space for managing virtual
functions (10.3) and virtual base classes (10.1)."
|
Do you have any idea what the rationale is for making "the order of
nonstatic data members separated by an access-specifier" unspecified?
I can't even fathom that. Why specify that the order of fields
without an intervening access specifier, but not fields with an
intervening access specifier? What is the benefit of allowing re-
ordering of fields which have different access specifiers? And - does
anyone know of a compiler that actually bothers to do this?
| Quote: | I have a question for you: Why should I use your library with my C++
code when you egregiously flout the language's rules? Try making your
code work within the constraints of the language, and you'll probably
have something more powerful.
I cannot add better words!
|
I explain my position in another post. But to answer the question
directly: I would love to not have to flout the language rules to do
what I am trying to do. I honestly believe that the language rules
are a little pedantic and arbitrary in some areas and that
unfortunately leads to this conflict between what I am trying to do
and what C++ wants to let me do. If you can think of a way for me to
generate code that has access to private and protected members of
unrelated classes, and does NOT require decorating the unrelated
classes in question with friend declarations or macros or somesuch,
and that also complies with the rules of C++, please let me know, I
would be overjoyed to use it.
Please keep in mind that the ONLY function of access specifiers in C++
is to ASSIST the programmer in designing classes the interactions
between which are well specified and can be checked by the compiler.
I am all for that. But as a means of ASSISTING the programmer, if
there are edge cases (such as what I am trying to do) where the
feature is more of a hindrance than a benefit, then you may agree that
it is unfortunate that there is no way in C++ to work around this
issue.
Honestly, if C++ had built-in full and complete runtime type
information, and also specified a serialized form for classes and
required compilers to be able to generate code to serialize objects,
then there would be no reason for me to try to bend the language rules
in these ways. I am hoping that if I can demonstrate the value of
such "natural" extensions to the language via my tool, then maybe
there will be some movement towards standardizing these things in the
language.
Thanks,
Bryan
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Guest
|
Posted: Sat May 12, 2007 4:28 am Post subject: Re: C++ private/protected hack |
|
|
On May 11, 2:55 pm, bji-gg...@ischo.com wrote:
| Quote: | On May 11, 9:32 pm, Ulrich Eckhardt <eckha...@satorlaser.com> wrote:
bji-gg...@ischo.com wrote:
I needed for some generated code to have access to private members and
methods of a class.
Make it a friend.
Thank you very much for your response.
The reason that I don't want to make it a friend is that I am trying
to graft functionality onto a class without requiring any changes to
that class. Thus I want to auto-generate code that calls methods of
the class and accesses member variables, but does so "stealthily"
without the original class ever having to declare that it was a friend
of the generated code.
For this reason, I don't want to use friend.
But I appreciate the suggestion; I think that if I didn't want to be
so stringent in my requirements that the original class *not* have to
declare another class a friend just to get my functionality, then
friend would work fine.
I guess you didn't follow the link I mentioned in my post - the Xrtti
project that I am working on attempts to add extended runtime type
information to classes without any modifications necessary to the
original class definitions. And when I say "not any", I mean, *not
any*. I want the extended runtime type information to "feel" like
it's a natural part of the language, not something that the definer of
the class has to "enable" by macros or friend declarations or any
other nonsense. This is my reason for not wanting to use friend.
|
I agree with your attempts to avoid macros and friend declarations.
We don't use those either. Instead we require users to add two
function prototypes (Send/Receive) to their classes. The definitions
of those functions are written by the service to a file separate
from the file containing the prototypes. If you don't make the
functions members, you wind up with a mess IMO. If you attempt
to mix generated and hand-written code, you will have an even
bigger mess. So we require users to make simple changes to
their classes.
Brian Wood
www.webEbenezer.net
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Guest
|
Posted: Sat May 12, 2007 4:30 am Post subject: Re: C++ private/protected hack |
|
|
On May 12, 3:04 pm, "Daniel T." <danie...@earthlink.net> wrote:
| Quote: | bji-gg...@ischo.com wrote:
Hey all. I would like some comments on yet another C++ "hack" that I
have employed in some work I have done (http://www.ischo.com/xrtti).
I had to employ this hack to "work around a limitation of the C++
language.
I don't see any limitation of the language which this hack would work
around (even if it did work.) Could you be more specific?
|
Well calling it a "limitation" of C++ is somewhat overstating the
case. It's more that the compiler is "limiting" me from being able to
break the access specifier mechanism. I think of it only as a
limitation of C++ in that C++ does not provide a mechanism for
deciding that although access specifiers are useful, in this one case,
I want my code to be able to ignore them.
But you are right in the fundamental point that you are making, and
that is that there really is no limitation of C++ per se. It's kind
of like how in C++, you can't modify members of a const class
instance, but you can cast the const class to a non-const class and
then modify that. If C++ disallowed this casting-away the constness
of a pointer or reference, then it would be "limiting" in the same
way, although it would be technically correct and there certainly
could be an argument that this is the way it should be, and that
allowing casting away const-ness is broken.
I guess the limitation I am talking about is the absence in C++ of a
"cast away private or protected access" mechanism, as there is for
const-ness. But once again, this really isn't a limitation per se,
it's just a strict feature of the language.
Anyway, that introductory paragraph I kinda just copied from my other
2 posts because they were all about similar "hacks"; I originally had
one email message for all 3 but it was too long.
Thanks!
Bryan
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Guest
|
Posted: Sat May 12, 2007 9:10 am Post subject: Re: C++ private/protected hack |
|
|
On May 12, 4:28 pm, c...@mailvault.com wrote:
| Quote: | I agree with your attempts to avoid macros and friend declarations.
We don't use those either. Instead we require users to add two
function prototypes (Send/Receive) to their classes. The definitions
of those functions are written by the service to a file separate
from the file containing the prototypes. If you don't make the
functions members, you wind up with a mess IMO. If you attempt
to mix generated and hand-written code, you will have an even
bigger mess. So we require users to make simple changes to
their classes.
|
That is a good approach; but it still requires some decoration of the
classes themselves (adding Send/Receive methods). This does have the
benefit of also tagging which classes need to have such code generated
for them so you don't have to have (as I do with Xrtti) an external
mechanism for specifying which classes to generate code for (I use
include and exclude command line arguments to the tool for this).
I am trying to avoid any decoration whatsoever. However, if it proves
necessary, I would consider something akin to what you describe.
Thank you,
Bryan
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Bo Persson Guest
|
Posted: Sat May 12, 2007 9:10 am Post subject: Re: C++ private/protected hack |
|
|
bji-ggcpp (AT) ischo (DOT) com wrote:
:: On May 12, 11:43 am, Daniel Krügler <daniel.krueg...@googlemail.com>
:: wrote:
::: On 11 Mai, 22:48, John Moeller <fishc...@gmail.com> wrote:
::
:::: Actually, I believe that every access section has to have its data
:::: in contiguous memory. But don't quote me on that. (Can anyone
:::: confirm/clarify/correct?)
:::
::: The essence is given by 9.2/12:
:::
::: "Nonstatic data members of a (non-union) class declared without an
::: intervening access-specifier are allocated so that later members
::: have higher addresses within a class object. The order of
::: allocation of nonstatic data members separated by an
::: access-specifier is unspecified (11.1). Implementation alignment
::: requirements might cause two adjacent members not to be allocated
::: immediately after each other; so might requirements for space for
::: managing virtual functions (10.3) and virtual base classes (10.1)."
::
:: Do you have any idea what the rationale is for making "the order of
:: nonstatic data members separated by an access-specifier" unspecified?
:: I can't even fathom that. Why specify that the order of fields
:: without an intervening access specifier, but not fields with an
:: intervening access specifier? What is the benefit of allowing re-
:: ordering of fields which have different access specifiers? And -
:: does anyone know of a compiler that actually bothers to do this?
It is actually the other way round. C++ has to define the order of public
members (of structs specifically), because the C language does so. As soon
as we get to the C++ specific part of the language, we can cast away the
compatibility burden.
The general idea is to leave as much room as possible to the compiler, by
not imposing unnecessesary restrictions. Some of us rather have well
optimized code, than a predictable layout of the private member variables.
Bo Persson
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Guest
|
Posted: Sat May 12, 2007 9:10 am Post subject: Re: C++ private/protected hack |
|
|
On May 12, 3:03 pm, John Moeller <fishc...@gmail.com> wrote:
| Quote: | What you sense as hostility is me just bluntly pointing out the
problems in your approach. You're undergoing a process of discovery
that many have performed. You just happen to be doing it publicly, so
you can't expect that you won't receive criticism.
I have weathered some criticism of my opinions on this group as well,
and many others have weathered it for a much longer time. It's a
blunt environment, and if what I say is incorrect, I expect the people
who know better than me to speak up and knock me down. And I'll take
it with a generous helping of humility.
Trust me, I'm not taking your questions personally; please don't take
my responses personally either.
|
Thank you for your response. Thanks especially for all of the great
information you have given me on these hacks that I am talking about.
Your responses have been very helpful; I was just sensing that your
patience was wearing thin with the last one, but I understand that you
were just being blunt and I have no problem with that. No harm, no
foul!
| Quote: | Fortunately, I do not and would not try to do something that makes
absolutely no sense, like the example you have given.
And in the context of C++, redefining keywords makes no sense either.
It seems to be a far-too-common hack, and its adoption should be
discouraged. If you don't like the access model, you shouldn't be
using C++.
|
But I disagree. There is a certain sense in saying "even though I
said when I defined this class that no one else should have access to
this data member ... well, I'm the programmer, and I say that here,
this code should really be given access too. Trust me, I know what I
am doing." I think that could be construed as a reasonable thing,
whereas trying to treat a floating point value as a class and call a
destructor method on it, when the concept of a floating point value
doesn't include anything *like* a destructor - now to me, that just
doesn't make sense. I think there is a difference between "stretching
the rules" in a way that makes some kind of sense (even if it has
flaws when certain aspects of the language are considered - and it is
these flaws that I am interested in discussing here), and something
completely nonsensical, as the example you gave.
And - as an aside - there are many things about C++ that I don't
like. In fact it disheartens me to see the direction that the
language has taken; instead of becoming more simple and concise (ala
Java), the addition of complex template syntax, template meta-
programming, more comprehensive support for shoot-yourself-in-the-foot
constructs like multiple inheritence and "diamond" inheritence ...
these things I just don't agree with. When I look at some modern C++
code, and especially the trends present in widely accepted tools and
libraries (Boost), it makes me not want to program C++ any more.
That being said, there is an aspect of C++ that I love - the comfort
of C-style syntax with all of the expressive power of object oriented
programming. I try to write all of my C++ code within certain
boundaries of what the language allows; and conveniently, these
boundaries also allow all of the "hacks" I have defined to work. I am
just trying to understand what aspects of these boundaries I may not
realize or may not be thinking about which make this stuff not
actually work even within my happy little world of "rational subset of
C++" (as I like to think of the language I program in when I write C++
code).
It was a long time ago, in college, when a friend and I discussed C++
and we agreed that it was a language that gives you more than enough
rope to hang yourself. It seems like over the years the rope has
gotten longer and longer - so long in fact, that it's hard not to trip
and fall into a noose even with the greatest of care. It doesn't help
that everyone else's libraries, tools, and methodologies for C++ seem
to be getting better and better at making really hard-to-see and ever-
more-pervasive nooses :)
| Quote: | Anyway, I don't know how my expectations about whether or not things
would break are relevent to the question of whether or not they *do*
break, which is what I am asking about.
Maybe I misunderstood. You spoke of this as a "technique," which I
infer that you claim that it works.
|
It *does* work - in a subset of cases; I just want to find out what
subset these are (which compilers, and with which assumptions about
the way compilers handle the C++ language). I have a *feeling* that
most or all compilers can be made to work with this hack. But I am
still trying to explore this issue to see if I'm correct on that.
| Quote: | Well my comment about Microsoft was just meant to be tongue-in-cheek.
I realize that my hack is not valid or guaranteed to work everywhere
(or anywhere), I just thought it would be oh-so-typical if the one
place where it ended up not working out in practice was with the MS
compiler. It was just a tongue-in-cheek comment though, not something
meant to be taken seriously.
My comments originate from sympathy for compiler writers from any
company or organization. It's difficult work to produce something as
complex as a C++ compiler. Additionally, I find anti-Microsoft jokes
in the realm of C++ to be kind of cliche. There's plenty of criticism
that can be arrayed against that company aside from their compiler,
which works pretty well for the Windows platform.
|
Point taken. I'll lay off the Microsoft bashing. It doesn't add
anything useful to the discussion anyway.
| Quote: | http://www.gotw.ca/gotw/076.htm
See the heading titled "Criminal #2".
I think I read that article some time ago, but I will look at it
again, thanks for the pointer. I am not deterred from my attempts to
do something useful for my code by my actions being thought of as
"criminal" though ...
Ok, now *you're* taking my tongue-in-cheek comments too seriously.
|
Well I thought the whole thing was kind of funny really. What I meant
in all seriousness is, the concensus on the kinds of hacks I am trying
are that they are well outside the realm of "legal" C++. Even though
I recognize this, I am not going to patently reject these hacks as
worthless if they end up solving my problem in a way that works with
all compilers I ever encounter. Sure, there's the chance that some
compiler can compeltely hose me - but if it's harder to hose me than
to not hose me, this leaves me with confidence that no one will ever
really bother.
| Quote: | If I were to use your library, I would not want it to modify the
behavior of my code, or rely on implementation-defined behavior.
Instead, I'd want it to leave my code alone. To do anything else
isn't "free," because it comes at the cost of modified behavior.
|
But it wouldn't modify the behavior of your code, as far as I know; it
uses read-only access to your class definitions and instances. It
just tries to compile code which can describe your classes, without
resorting to inheritence or friend or macro tricks. It does leave
your code alone. It doesn't *touch* your original header files, or
ask you to; it just generates an innocuous C++ source file which uses
lots of hacks to try to give you some functionality that you will find
useful.
Now when I get to the actual implementation of serialization, that
will be a little different story. This is because, as much as it
pains me, there is no way to implement completely transparent
serialization for any arbitrary C++ class. There are going to have to
be "rules" that need to be followed in order for a class to be
serializable (for example, all arrays will need to have standardizes
means for finding out the number of elements in the array at runtime -
typically by a "count" member which must be maintained with certain
semantics). This will impact on your class file definitions. And
this sucks horribly and I hate this fact. But that's a whole other
ball of wax that we can talk about when I have released the
serialization tool built on top of Xrtti.
| Quote: | For what it's worth, I have had some discussion with graduate student
at VA Tech who says that they have a solution to my problem (getting
access to private and protected members of classes) without having to
do any preprocessor games. He claims that their solution took a week
of thinking to come up with and that it will give me an "a-ha" moment
when I see how they do it. I am hoping to incorporate what they have
done into my project instead of relying on #define hacks. ...
I think that's excellent, and you should pursue more
language-conforming methods.
|
Thank you, I certainly will. Despite my assertions that I want to use
these hacks, please understand that I only want to do so because I can
see no other way to implement the tool with the properties that I want
it to have. If and when a means can be discovered to use language-
conforming methods to do these things, I will gladly throw away my
hacks and not shed even the smallest tear.
Thanks again!
Bryan
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Bo Persson Guest
|
Posted: Sat May 12, 2007 9:10 am Post subject: Re: C++ private/protected hack |
|
|
bji-ggcpp (AT) ischo (DOT) com wrote:
:: On May 12, 3:04 pm, "Daniel T." <danie...@earthlink.net> wrote:
::: bji-gg...@ischo.com wrote:
:::: Hey all. I would like some comments on yet another C++ "hack"
:::: that I have employed in some work I have done
:::: (http://www.ischo.com/xrtti). I had to employ this hack to "work
:::: around a limitation of the C++ language.
:::
::: I don't see any limitation of the language which this hack would
::: work around (even if it did work.) Could you be more specific?
::
:: Well calling it a "limitation" of C++ is somewhat overstating the
:: case. It's more that the compiler is "limiting" me from being able
:: to break the access specifier mechanism. I think of it only as a
:: limitation of C++ in that C++ does not provide a mechanism for
:: deciding that although access specifiers are useful, in this one
:: case, I want my code to be able to ignore them.
You can, if the classes involved decide to let you do it. You just cannot
force it upon everyone!
::
:: But you are right in the fundamental point that you are making, and
:: that is that there really is no limitation of C++ per se. It's kind
:: of like how in C++, you can't modify members of a const class
:: instance, but you can cast the const class to a non-const class and
:: then modify that. If C++ disallowed this casting-away the constness
:: of a pointer or reference, then it would be "limiting" in the same
:: way, although it would be technically correct and there certainly
:: could be an argument that this is the way it should be, and that
:: allowing casting away const-ness is broken.
You can't cast away constness on a class that is actually const. You can
cast away the constness of a pointer of reference only if the object
referred to is not actually const in itself. You are just modifying the
access, not the real object.
::
:: I guess the limitation I am talking about is the absence in C++ of a
:: "cast away private or protected access" mechanism, as there is for
:: const-ness. But once again, this really isn't a limitation per se,
:: it's just a strict feature of the language.
There is such a feature, the friend concept. The difference is that each
class has to define who are its friends, that is not up to the wannabe
"friends" to decide.
Think about it - if I write a class with some private data, I want to be in
control of all the updates of this piece of information. That might be
crucial to be able to guarantee the consistency of the object. Now, if some
other object could decide that it should have access to my data, how am
I to
handle that?
Bo Persson
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Daniel T. Guest
|
Posted: Sat May 12, 2007 7:00 pm Post subject: Re: C++ private/protected hack |
|
|
bji-ggcpp (AT) ischo (DOT) com wrote:
| Quote: | On May 12, 3:04 pm, "Daniel T." <danie...@earthlink.net> wrote:
bji-gg...@ischo.com wrote:
Hey all. I would like some comments on yet another C++ "hack"
that I have employed in some work I have done
(http://www.ischo.com/xrtti). I had to employ this hack to "work
around a limitation of the C++ language.
I don't see any limitation of the language which this hack would
work around (even if it did work.) Could you be more specific?
Well calling it a "limitation" of C++ is somewhat overstating the
case. It's more that the compiler is "limiting" me from being able
to break the access specifier mechanism.
|
I think though, that this might explain why you have started to "sense
some hostility" in some people's responses. To call a mechinism designed
to help ensure safety a "limitation" is somewhat unkind IMHO.
| Quote: | I think of it only as a limitation of C++ in that C++ does not
provide a mechanism for deciding that although access specifiers are
useful, in this one case, I want my code to be able to ignore them.
|
The basic problem here is that the designer of the class found the
specifiers useful but you are deciding for him that he was wrong.
I personally don't think that there is any "extended runtime"
information that you could provide that would both be useful, and
require the breaking of access specifications. Maybe an example of use
would help?
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Guest
|
Posted: Sat May 12, 2007 7:01 pm Post subject: Re: C++ private/protected hack |
|
|
On May 12, 3:15 am, bji-gg...@ischo.com wrote:
| Quote: | On May 12, 4:28 pm, c...@mailvault.com wrote:
I agree with your attempts to avoid macros and friend declarations.
That is a good approach; but it still requires some decoration of the
classes themselves (adding Send/Receive methods). This does have the
benefit of also tagging which classes need to have such code generated
for them so you don't have to have (as I do with Xrtti) an external
mechanism for specifying which classes to generate code for (I use
include and exclude command line arguments to the tool for this).
I am trying to avoid any decoration whatsoever. However, if it proves
necessary, I would consider something akin to what you describe.
|
It is necessary. How would your stuff know what to do with file
descriptors, mutexes, condition variables and things like that?
There has to be a way to indicate some things shouldn't be
marshalled.
I suppose with a lot of effort you could come up with some solutions
that would satisfy 90% of the compilers. Thing is those vendors
may not appreciate your success and can make some changes to
their next release to throw a wrench in your approach. They laugh
all the way to the bank. Your approach is too fragile that way.
How come Kanze doesn't write much/anything lately? I hope he is ok.
Brian Wood
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Seungbeom Kim Guest
|
Posted: Sun May 13, 2007 2:39 am Post subject: Re: C++ private/protected hack |
|
|
bji-ggcpp (AT) ischo (DOT) com wrote:
| Quote: |
And - as an aside - there are many things about C++ that I don't
like. In fact it disheartens me to see the direction that the
language has taken; instead of becoming more simple and concise (ala
Java), the addition of complex template syntax, template meta-
programming, more comprehensive support for shoot-yourself-in-the-foot
constructs like multiple inheritence and "diamond" inheritence ...
these things I just don't agree with. When I look at some modern C++
code, and especially the trends present in widely accepted tools and
libraries (Boost), it makes me not want to program C++ any more.
|
Those that are simple to learn tend to be limiting in their features,
and vice versa. For example, without multiple inheritance, there would
be cases served worse by C++. Other languages make things simpler by
limiting its power and expressivity.
A blunt knife is safer and easier to learn to use but less powerful.
A sharp knife is more powerful but more dangerous and harder to learn.
A short password is easier to remember but less secure, and a long
one is more secure but harder to remember. Many things are like that.
(Yes, there are things that are too arcane without offering obvious
benefits, e.g. the declaration syntax. Just because the language is
designed by people and people are not perfect.)
| Quote: | That being said, there is an aspect of C++ that I love - the comfort
of C-style syntax with all of the expressive power of object oriented
programming.
|
Isn't it roughly what Java gives as well?
| Quote: | I try to write all of my C++ code within certain
boundaries of what the language allows;
[...] within my happy little world of "rational subset of
C++" (as I like to think of the language I program in when I write C++
code).
|
I try to stay away from guidelines that tell me to stay away from
certain features just because they are dangerous. I know the perils of
goto, but I'm not reluctant to use it when I know it's useful. I see
it very unfortunate that there are many people who say "Don't use RTTI;
it's too expensive." or "Don't use multiple inheritance; it's too error-
prone." without understanding how they work or how useful they can be.
--
Seungbeom Kim
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Sebastian Redl Guest
|
Posted: Sun May 13, 2007 2:45 am Post subject: Re: C++ private/protected hack |
|
|
On Fri, 11 May 2007 bji-ggcpp (AT) ischo (DOT) com wrote:
| Quote: | Do you have any idea what the rationale is for making "the order of
nonstatic data members separated by an access-specifier" unspecified?
I can't even fathom that. Why specify that the order of fields
without an intervening access specifier, but not fields with an
intervening access specifier?
|
Francis Glasborough gave me an idea of how to make use of this fact.
Consider this class (interface omitted):
class Foo
{
char a;
int b;
short c;
double d;
};
As every programmer knows, this class will most likely be larger than the
sum of its parts due to padding. On your bog standard x86 compiler, it
will probably be 24 bytes large, when the sum of its parts is only 15.
That's over 50% overhead.
If a compiler was allowed to rearrange data at will, it could reorder the
fields to this far more efficient arrangement, without the programming
having to destroy his own order (which might make sense due to the
semantics of the members):
class Foo
{
double d;
int b;
short c;
char a;
};
The new class will probably have only a single byte of padding at the end,
bringing its total size to 16 bytes, getting rid of 8 bytes of overhead
and a third of the total size.
Now, C compatibility doesn't allow full reordering. POD structs must
remain layout-compatible with C structs. The approach taken by the
committee is something of a compromise: as long as there are no access
specifiers in-between, it's in order. Put one there and the doors are
open.
Personally, I think C++ could be even more loose than the current state:
1) POD classes have their members ordered in memory the same way as in the
definition.
2) Non-POD classes have arbitrary order on their elements.
That would suffice for C compatibility and give more opportunity for
reordering. It might even encourage compiler writers to actually implement
this optimization.
Sebastian Redl
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Sebastian Redl Guest
|
Posted: Sun May 13, 2007 2:46 am Post subject: Re: C++ private/protected hack |
|
|
On Sat, 12 May 2007 bji-ggcpp (AT) ischo (DOT) com wrote:
| Quote: | But I disagree. There is a certain sense in saying "even though I
said when I defined this class that no one else should have access to
this data member ... well, I'm the programmer, and I say that here,
this code should really be given access too. Trust me, I know what I
am doing."
|
That's what friend declarations are for. What you are describing, however,
is: "Look, I didn't write this class (or at least I can't modify it
anymore), but I really think I should be able to access its internals. I
know what I'm doing."
And the answer is, "Yeah, right. You can't modify the class, but you claim
to know what you're doing?"
The "programmer" that wants access to my class is not me. Depending on
your point of view it's either your data extractor (a tool) or its author,
you. Neither of which, frankly, I trust to keep my object's invariants.
| Quote: | And - as an aside - there are many things about C++ that I don't
like. In fact it disheartens me to see the direction that the
language has taken;
|
I don't get it. Direction from where? Multiple inheritance has been there
nearly since the beginning. Virtual inheritance is a necessary
consequence. Are you disheartened that those features weren't removed in
C++09? You know that removing a complete language feature just isn't
feasible. New language standards must keep some level of backward
compatibility. Template syntax has become easier: concepts ease the
writing of templates. Concept-based overloading largely removes the
necessity of traits classes, enable_if decisions and SFINAE hacks.
Template varargs cut down on preprocessor-generated repeated versions of
the same template. Automatic type deduction removes the need for unwieldy
type specifiers. The underlying feature, templates, has been in the
language for a long time, and been a wish fulfilled by ugly hacks nearly
since day one. Again I fail to see where the "direction" you speak of is.
| Quote: | these things I just don't agree with. When I look at some modern C++
code, and especially the trends present in widely accepted tools and
libraries (Boost), it makes me not want to program C++ any more.
|
So program in that nice and concise language you mentioned, Java. Or C#.
Really. If you think Boost is a bad example of programming, C++ is
probably not for you. Personally I love the incredible features of C++
that allow DSELs to be compiled by the normal C++ compiler.
| Quote: | That being said, there is an aspect of C++ that I love - the comfort
of C-style syntax with all of the expressive power of object oriented
programming.
|
Java and C# fulfill these needs.
| Quote: | It was a long time ago, in college, when a friend and I discussed C++
and we agreed that it was a language that gives you more than enough
rope to hang yourself.
|
So does C. So does every other language in existence, for that matter. You
can hang yourself quite easily in Java, believe me.
| Quote: | It seems like over the years the rope has gotten longer and longer - so
long in fact, that it's hard not to trip and fall into a noose even with
the greatest of care.
|
I don't get it. The language hasn't changed in years. How can the rope
have gotten longer?
| Quote: | It doesn't help that everyone else's libraries, tools, and methodologies
for C++ seem to be getting better and better at making really
hard-to-see and ever-more-pervasive nooses
|
How can a library be a noose? How can someone else's methodologies
possibly make programming more difficult for you?
Sebastian Redl
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|