By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,534 Members | 1,807 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,534 IT Pros & Developers. It's quick & easy.

Template technicality - What does the standard say?

P: n/a

I've been using Visual C++ 2003 for some time, and recently started
working on making my code compile in GCC and MinGW. I hit on lots of
unexpected problems which boil down to the same template issue. A
noddy mixin layer example should illustrate the issue...

class Base
{
protected:
int m_Field;

public:
Base () : m_Field (0) {}
};

template<class Tclass Derived : public T
{
public:
void Inc ()
{
T::m_Field++; // GCC needs the "T::" here - VC++ doesn't
}
};

In the above, the idea is to use Derived<Base>, but GCC (3.4.5 and
4.1.2) gives error messages even if you never instantiate the
template.

There are of course examples of similar templates in Stroustrup, but
because they are incomplete examples, I can't find one that shows an
inherited member being referenced from within the template class.

In non-template classes, scope resolution is only needed to access
inherited members if there is an ambiguity. There is no ambiguity in
the above - the only place m_Field can come from is the inherited
class Base via the template parameter T. Following that general
principle, I don't see any reason why scope resolution should be
needed.

What does the standard say about this - should the scope resolution
operator be required? If it is required, what's the rationale? If
there's something in Stroustrup about this, can you point me to the
right section?

Oct 13 '08 #1
Share this Question
Share on Google+
32 Replies


P: n/a
On Mon, 13 Oct 2008 09:12:09 +0200, Michael DOUBEZ
<mi************@free.frwrote:
>Look up template-dependant name:
http://www.parashift.com/c++-faq-lit...html#faq-35.19
Thanks.

Just read 35.18, 35.19 and 35.20. Now I *know* that the lunatics are
running the asylum. Different scoping/lookup rules depending on
whether something is "dependent" or "non-dependent" - pathetic. Next
it'll be phases of the moon.

Anyway, now that's done, I just have to figure out why GCC won't let
me use offsetof in a constant expression - ie in exactly the kind of
place you're always going to use offsetof. Where the last lot was an
"oh well, a few hours hunting and fixing" thing, this is a real
killer.

I have huge amounts of data-driven code that *needs* to use offsetof
in constant expressions to initialise static data. I also have code
generators that generate code using offsetof in constant expressions.
It'd be easier to develop my own offshoot of C++ than to never use
offsetof in constant expressions. It's the kind of thing people have
been doing in C and C++ since dinosaurs roamed the Earth, and frankly,
if someone has decided to ban it, that someone is a moron.

Sigh.

Oct 13 '08 #2

P: n/a
Stephen Horne wrote:
On Mon, 13 Oct 2008 09:12:09 +0200, Michael DOUBEZ
<mi************@free.frwrote:
>Look up template-dependant name:
http://www.parashift.com/c++-faq-lit...html#faq-35.19

Thanks.

Just read 35.18, 35.19 and 35.20. Now I *know* that the lunatics are
running the asylum. Different scoping/lookup rules depending on
whether something is "dependent" or "non-dependent" - pathetic. Next
it'll be phases of the moon.

Anyway, now that's done, I just have to figure out why GCC won't let
me use offsetof in a constant expression - ie in exactly the kind of
place you're always going to use offsetof. Where the last lot was an
"oh well, a few hours hunting and fixing" thing, this is a real
killer.
GCC does not let you use it as a constant because the standard says so.
SUCCS, I know, just is. You may get some luck out of using pointer to
member types.
>
I have huge amounts of data-driven code that *needs* to use offsetof
in constant expressions to initialise static data. I also have code
generators that generate code using offsetof in constant expressions.
It'd be easier to develop my own offshoot of C++ than to never use
offsetof in constant expressions. It's the kind of thing people have
been doing in C and C++ since dinosaurs roamed the Earth, and frankly,
if someone has decided to ban it, that someone is a moron.
You can probably refactor to use pointer to member.

If you have a code example, post it in a new thread and lets see if we
can give you a few suggestions.
Oct 13 '08 #3

P: n/a
On 2008-10-13 14:38, Gianni Mariani wrote:
Stephen Horne wrote:
>On Mon, 13 Oct 2008 09:12:09 +0200, Michael DOUBEZ
<mi************@free.frwrote:
>>Look up template-dependant name:
http://www.parashift.com/c++-faq-lit...html#faq-35.19

Thanks.

Just read 35.18, 35.19 and 35.20. Now I *know* that the lunatics are
running the asylum. Different scoping/lookup rules depending on
whether something is "dependent" or "non-dependent" - pathetic. Next
it'll be phases of the moon.

Anyway, now that's done, I just have to figure out why GCC won't let
me use offsetof in a constant expression - ie in exactly the kind of
place you're always going to use offsetof. Where the last lot was an
"oh well, a few hours hunting and fixing" thing, this is a real
killer.

GCC does not let you use it as a constant because the standard says so.
SUCCS, I know, just is. You may get some luck out of using pointer to
member types.
What is it that I'm missing, offsetof is a macro, it should be expanded
before the compiler can even begin worrying about whether an expression
is constant or not.

--
Erik Wikström
Oct 13 '08 #4

P: n/a
On Oct 13, 6:08 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2008-10-13 14:38, Gianni Mariani wrote:
Stephen Horne wrote:
On Mon, 13 Oct 2008 09:12:09 +0200, Michael DOUBEZ
<michael.dou...@free.frwrote:
>Look up template-dependant name:
http://www.parashift.com/c++-faq-lit...html#faq-35.19
Just read 35.18, 35.19 and 35.20. Now I *know* that the
lunatics are running the asylum. Different scoping/lookup
rules depending on whether something is "dependent" or
"non-dependent" - pathetic. Next it'll be phases of the
moon.
Anyway, now that's done, I just have to figure out why GCC
won't let me use offsetof in a constant expression - ie in
exactly the kind of place you're always going to use
offsetof. Where the last lot was an "oh well, a few hours
hunting and fixing" thing, this is a real killer.
GCC does not let you use it as a constant because the
standard says so. SUCCS, I know, just is. You may get some
luck out of using pointer to member types.
What is it that I'm missing, offsetof is a macro, it should be
expanded before the compiler can even begin worrying about
whether an expression is constant or not.
I'm just guessing, because of course, g++ lets you use a legal
offsetof as a constant, but I'll bet he's actually trying to use
it on something that isn't a PODs, which is undefined behavior.
In that case, g++ generates an error; a lot of compilers will
just give you some random (constant) value.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 13 '08 #5

P: n/a
On Mon, 13 Oct 2008 12:38:51 GMT, Gianni Mariani
<gi*******@mariani.wswrote:
>Stephen Horne wrote:
>On Mon, 13 Oct 2008 09:12:09 +0200, Michael DOUBEZ
<mi************@free.frwrote:
>>Look up template-dependant name:
http://www.parashift.com/c++-faq-lit...html#faq-35.19
>Anyway, now that's done, I just have to figure out why GCC won't let
me use offsetof in a constant expression - ie in exactly the kind of
place you're always going to use offsetof. Where the last lot was an
"oh well, a few hours hunting and fixing" thing, this is a real
killer.

GCC does not let you use it as a constant because the standard says so.
SUCCS, I know, just is. You may get some luck out of using pointer to
member types.
No - GCC didn't let me use it because it didn't know that the
class/struct parameter was a class/struct, reason being I needed to
add 'typename'. GCC was entirely in the right, and I'd even count it
as a pretty sane aspect of the standard.

It's a bit strange, actually. The errors suggested that GCC does a
pointer-casting macro expansion for offsetof, but as far as I can
tell, what it's supposed to do is macro-expand to a built-in along the
lines of __offsetof__ (that's probably spelt wrong, but you get the
idea).

Anyway, turns out that's the easier thing to fix. Some of the
dependent stuff inheritance problems aren't so easy to fix - when they
work in GCC, they break in VC++ and visa versa. I feel superfluous
private inline access methods with #ifdef bodies approaching in the
near future.

Pointer-to-member types are a problem for several reasons, portability
being one of them since VC++ and probably others need you to drop
nonstandard hints about whether the class is single inheritance,
multiple inheritance or whatever. And when you do use them, the syntax
is a mess, and no-one can read it because no-one uses them enough to
get that used to them. Another one of those untested ideas the
standards people dreamed up, that don't really work in practice.

Oct 14 '08 #6

P: n/a
On Mon, 13 Oct 2008 10:08:32 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>On Oct 13, 6:08 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
>What is it that I'm missing, offsetof is a macro, it should be
expanded before the compiler can even begin worrying about
whether an expression is constant or not.

I'm just guessing, because of course, g++ lets you use a legal
offsetof as a constant, but I'll bet he's actually trying to use
it on something that isn't a PODs, which is undefined behavior.
In that case, g++ generates an error; a lot of compilers will
just give you some random (constant) value.
No.

Read for tone and you'll see I'm seriously pissed off and frustrated,
and that thing about offsetof was ranting rather than a properly
organised request for help. For example, no quoted error messages.

Anyway, I said that GCC wouldn't let me use offsetof in a constant
expression, which *was* perfectly true. I also said "now I have to
figure out why" which I have since done.

The GCC errors directed me to lines that contained nothing much more
than offsetof, and complained about pointer operators etc that weren't
there (hence macro expansion). I just recently read the part of the
GCC manual that tells me it defines offsetof to map to a builtin,
unless I dreamed that up in a stress-related psychotic episode (it's
pretty bad when you hallucinate about reading manuals), making the
macro-expansion-implying errors seem strange.

Some other code relating to alignment used hand-written code that
effectively does an offsetof. When GCC complained about that, I fixed
it by simply using offsetof instead. This seems to suggest GCC is
actually doing something different to macro expansion, since replacing
the code that the macro is traditional expanded to with the macro gave
different behaviour. I guess it doesn't really matter, so long as
offsetof works, which it does - my problem was due to being in a
template again, and the need for "typename", which is perfectly
reasonable for a change.
You've got my interest, though. Why on earth should offsetof for a
non-POD struct/field be undefined? POD vs. non-POD shouldn't change
the layout of a struct. A non-POD struct might act as if it holds
extra data, though that data is external to the struct, but that has
nothing to do with offsetof. Some fields may be private and
inaccessible to offsetof (a compile-time error), some fields may be
pointers or references (not an error - just means you're referring to
the pointer), but that applies to POD and non-POD equally.

Also, it's not as if the macro expansion ever instantiates the type.
It just "imagines" a hypothetical instance at address zero and takes
the address of the field.

About the only thing I can think of which could *almost* legitimately
screw up offsetof would be overriding the * or -pointer dereference
operators, but even if a macro expansion of offsetof uses ->, it uses
it with a *pointer* left argument rather than the non-pointer object,
so the override is irrelevant. Same goes if the macro uses * and .
instead.

Can you give me a reference to look this up?

I mean, the idea that I can't take the offsetof a field in a data
structure node just because the application is using a non-POD type
for the contained data is beyond ridiculous.

In keeping with my generally pissed-off tone, I'll also ask if the
standards people came up with this one specifically to drive me nuts?
Or are you just baiting me for fun?

Oct 14 '08 #7

P: n/a
On Oct 14, 4:58 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
On Mon, 13 Oct 2008 10:08:32 -0700 (PDT), James Kanze
<james.ka...@gmail.comwrote:
On Oct 13, 6:08 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
What is it that I'm missing, offsetof is a macro, it should
be expanded before the compiler can even begin worrying
about whether an expression is constant or not.
I'm just guessing, because of course, g++ lets you use a
legal offsetof as a constant, but I'll bet he's actually
trying to use it on something that isn't a PODs, which is
undefined behavior. In that case, g++ generates an error; a
lot of compilers will just give you some random (constant)
value.
No.
Read for tone and you'll see I'm seriously pissed off and
frustrated, and that thing about offsetof was ranting rather
than a properly organised request for help. For example, no
quoted error messages.
I understood that you were pissed off. Still, g++ is fully
conform with regards to offsetof, and does allow it's use in an
integral constant expression. So presumably, your real problem
is elsewhere. And since most compilers don't complain about use
of offsetof on a non-POD, but g++ does, I made a guess that that
might be the real problem.
Anyway, I said that GCC wouldn't let me use offsetof in a
constant expression, which *was* perfectly true.
No it's not. The following code compiles perfectly well with
g++:

#include <cstddef>
#include <iostream>

struct S
{
int i ;
int j ;
int k ;
} ;

int
main()
{
char a[ offsetof( S, k ) ] ;
std::cout << sizeof( a ) << std::endl ;
return 0 ;
}

You're doing something else wrong.
I also said "now I have to figure out why" which I have since
done.
The GCC errors directed me to lines that contained nothing
much more than offsetof, and complained about pointer
operators etc that weren't there (hence macro expansion). I
just recently read the part of the GCC manual that tells me it
defines offsetof to map to a builtin, unless I dreamed that up
in a stress-related psychotic episode (it's pretty bad when
you hallucinate about reading manuals), making the
macro-expansion-implying errors seem strange.
Some other code relating to alignment used hand-written code
that effectively does an offsetof. When GCC complained about
that, I fixed it by simply using offsetof instead. This seems
to suggest GCC is actually doing something different to macro
expansion, since replacing the code that the macro is
traditional expanded to with the macro gave different
behaviour. I guess it doesn't really matter, so long as
offsetof works, which it does - my problem was due to being in
a template again, and the need for "typename", which is
perfectly reasonable for a change.
Fine. The problem wasn't due to g++'s expansion of offsetof not
being a constant integral expression; it was due to a syntax
error elsewhere.

For the record, g++ defines offsetof as a macro (as required by
the standard), but that macro expands to something like
"__builtin_offsetof( t, e )" (which is, IMHO, the only
reasonable way of implementing it). So what you actually get is
a compiler built in, which is either a constant integral
expression, or causes an error, depending on whether the use of
offsetof is legal or not.
You've got my interest, though. Why on earth should offsetof
for a non-POD struct/field be undefined?
Because it can't be implemented in the general case, and no one
considered it worth the effort of specifying when it would be
legal, and when not, except for a PODS, which is all that is
necessary for C compatibility (and the only reason it's there is
for reasons of C compatibility).
POD vs. non-POD shouldn't change the layout of a struct.
In some cases of inheritance (particularly where virtual
inheritance is involved), the layout is dynamically defined; the
compiler doesn't know it. And the "classical" implementation of
offsetof in C is something like:

#define offsetof( S, e ) ((size_t)(&(((S*)0)->e)))

Which is undefined behavior if you write it, but which the
library implementor can do if he knows that it will get by the
compiler.

Many libraries (e.g. Sun CC, VC++) still use something like
this, and the standards committee didn't want to ban it. And it
fails as soon as the member is private.
A non-POD struct might act as if it holds extra data, though
that data is external to the struct, but that has nothing to
do with offsetof. Some fields may be private and inaccessible
to offsetof (a compile-time error), some fields may be
pointers or references (not an error - just means you're
referring to the pointer), but that applies to POD and non-POD
equally.
References could also cause problems. In general, it would
doubtlessly be possible to loosen the rules somewhat. Doing so
would require a fairly detailed analysis, however, to ensure
that the new rules didn't cause any problem for potential
implementations, and no one on the committee felt the effort was
worthwhile. (The case of POD was "established practice", from
C.)
Also, it's not as if the macro expansion ever instantiates the
type. It just "imagines" a hypothetical instance at address
zero and takes the address of the field.
About the only thing I can think of which could *almost*
legitimately screw up offsetof would be overriding the * or ->
pointer dereference operators, but even if a macro expansion
of offsetof uses ->, it uses it with a *pointer* left argument
rather than the non-pointer object, so the override is
irrelevant. Same goes if the macro uses * and . instead.
Can you give me a reference to look this up?
To look what up? The standard says quite clearly (§18.1/5):

The macro offsetof accepts a restricted set of type
arguments in this International Standard. type shall be
a POD structure or a a POD union. The result of
applying the offsetof macro to a field that is a static
data member or a function member is undefined.
I mean, the idea that I can't take the offsetof a field in a
data structure node just because the application is using a
non-POD type for the contained data is beyond ridiculous.
No. It's a perfectly reasonable constraint.
In keeping with my generally pissed-off tone, I'll also ask if
the standards people came up with this one specifically to
drive me nuts? Or are you just baiting me for fun?
Actually, they're just trying to strike a compromise between the
ideal solution (drop the macro entirely) and C compatibility.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 14 '08 #8

P: n/a
On Oct 14, 4:08 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
On Mon, 13 Oct 2008 12:38:51 GMT, Gianni Mariani
<gi4nos...@mariani.wswrote:
[...]
Pointer-to-member types are a problem for several reasons,
portability being one of them since VC++ and probably others
need you to drop nonstandard hints about whether the class is
single inheritance, multiple inheritance or whatever.
That's not quite true. VC++ does require special compiler
options to truly be a C++ compiler (but that's true of all
compilers I know), but if you use them (/vmg, in this case),
pointers to members cause no problems. (At least that I can
tell; most of my experience with pointers to members has been
with pointer to member functions, which definitly don't work
with VC++ unless you specify this option.)
And when you do use them, the syntax is a mess, and no-one can
read it because no-one uses them enough to get that used to
them. Another one of those untested ideas the standards people
dreamed up, that don't really work in practice.
Sort of. In practice, there just isn't that much use for
pointers to members, so there's really no need for a
particularly simple syntax. And the syntax for using pointers
to a data member isn't that bad, either, although I can see
people getting a bit bothered when pointers to member functions
are involved.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 14 '08 #9

P: n/a
Stephen Horne wrote:
On Tue, 14 Oct 2008 01:34:49 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>Sort of. In practice, there just isn't that much use for
pointers to members, so there's really no need for a
particularly simple syntax.

This from the guy who just declared that offsetof is only there for C
compatibility, and shouldn't be used.

OK - what's the alternative, then?

You give the impression of being someone who does serious work, and
has almost certainly worked on containers and other low-level
libraries. To hold these opinions, I can only guess that you're either
benefiting from the compiler-vendors I-can-but-you-can't clause, or
else you're one of the standards guys - quite possibly both.
Maybe James, like me, in many years of C++ development has never needed
pointers to members, or offsetof. Before you ask, most of my work has
been low level libraries.

--
Ian Collins
Oct 14 '08 #10

P: n/a
On Oct 14, 10:38*pm, Stephen Horne <sh006d3...@blueyonder.co.uk>
wrote:
On Tue, 14 Oct 2008 01:34:49 -0700 (PDT), James Kanze
<james.ka...@gmail.comwrote:
Sort of. *In practice, there just isn't that much use for
pointers to members, so there's really no need for a
particularly simple syntax.
This from the guy who just declared that offsetof is only
there for C compatibility, and shouldn't be used.
OK - what's the alternative, then?
What problem do they solve? I've used pointer to member
functions a couple of times, but never a pointer to a data
member.
You give the impression of being someone who does serious
work, and has almost certainly worked on containers and other
low-level libraries. To hold these opinions, I can only guess
that you're either benefiting from the compiler-vendors
I-can-but-you-can't clause, or else you're one of the
standards guys - quite possibly both.
Neither. I've just never found any need for pointers to a data
member. Nor offsetof. They're solutions looking for a problem.

And FWIW, I've implemented a full C standard library, and
several pre-standard container libraries for C++. I've also
implemented marshalling/demarshalling code for low-level data
communications, persistency and the like. And memory management
(globale operator new()/operator delete()). I have needed some
non-standard features: open(),read(),write(),close(), etc. for
my implementation of <stdio.h>, sbrk() for my implementation of
malloc/free (this was before mmap() was an option), etc. Even
today, I need non-standard features for some of my work.

There are some important features which are missing in C++. The
possibility to specify alignment, for example. (I actually
wrote a proposal for this for the C90 standard, but I think I
submitted it a bit too late.) And some support for full data
synchronization in the standard library; I can't use fstream for
persistency because of this. More generally, the absence of
garbage collection means I have to write a lot of code which
would otherwise be unnecessary.

I can't see any need for offsetof, however.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 14 '08 #11

P: n/a
Stephen Horne wrote:
On Tue, 14 Oct 2008 15:58:15 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>Why should you have the right to find the offset of a data
member, period?

Because without it, C++ is not fit for purpose, period.
Cutting though the waffle, why?

I've been using C++ for everything from drivers to libraries to GUIs as
a major part of my day job for many years and I've never had cause to
find the offset of a data member.

--
Ian Collins
Oct 15 '08 #12

P: n/a
On Wed, 15 Oct 2008 14:50:35 +1300, Ian Collins <ia******@hotmail.com>
wrote:
>Stephen Horne wrote:
>On Tue, 14 Oct 2008 15:58:15 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>>Why should you have the right to find the offset of a data
member, period?

Because without it, C++ is not fit for purpose, period.
Cutting though the waffle, why?

I've been using C++ for everything from drivers to libraries to GUIs as
a major part of my day job for many years and I've never had cause to
find the offset of a data member.
Search for "thin wrapper" in the post.

Oct 15 '08 #13

P: n/a
Stephen Horne wrote:
On Tue, 14 Oct 2008 15:58:15 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>>>In some cases of inheritance (particularly where virtual
inheritance is involved), the layout is dynamically defined;
I can see that there is a potential problem with a macro
expansion implementation (rather than GCCs wrapper approach)
to offsetof, since doing the field reference would access the
virtual table/whatever of an object that doesn't exist.
Even so, the layout of the class isn't dynamically defined,
it's just dynamically accessed.
Sorry, but when virtual inheritance is involved, it's
dynamically defined. At least with all of the compilers I know,
and I don't think it's possible to implement it otherwise.

I'm sorry, but it's basic textbook. The compiler determines what is
inherited and places each inherited class at a particualar offset
within the derived class, as if it were member data (which it is).
This isn't true. See 9.2.12 and 10.0.5.

--
Ian Collins
Oct 15 '08 #14

P: n/a
Stephen Horne wrote:
>
In my current circumstances, paying for the standard would mean not
eating for a week,
You can live off $18 a week, I'm impressed.
A constraint that means C data structure code cannot be adapted and
wrapped in a C++ template? IIRC, one of the basic design principles of
C++ is that people should be able to adapt their C libraries without a
complete rewrite.
By definition, a C data structure is a POD struct, so you can use offsetof.
Trying to bully people into using member-pointers won't fix the flaws.
offsetof is needed, like it or not. Without it, there is simply *NO*
sane way for library developers to develop production quality
containers.
It's never stopped me, or all the other C++ library writers out there.

--
Ian Collins
Oct 15 '08 #15

P: n/a
On Wed, 15 Oct 2008 16:39:32 +1300, Ian Collins <ia******@hotmail.com>
wrote:
>Stephen Horne wrote:
>>
In my current circumstances, paying for the standard would mean not
eating for a week,

You can live off $18 a week, I'm impressed.
Not quite *that* tight, but 'live' is questionable anyway. That's not
the price I saw for the standard (or the one James quoted).

If that price is available, next problem is no credit card. I refuse
to get one so long as I'm on benefits for obvious reasons.
>A constraint that means C data structure code cannot be adapted and
wrapped in a C++ template? IIRC, one of the basic design principles of
C++ is that people should be able to adapt their C libraries without a
complete rewrite.
By definition, a C data structure is a POD struct, so you can use offsetof.
template<typename T>
struct This_May_Not_Be_POD
{
T Because_This_May_Not_Be_POD;
};

That's the whole point.

Oct 15 '08 #16

P: n/a
On Wed, 15 Oct 2008 16:30:54 +1300, Ian Collins <ia******@hotmail.com>
wrote:
>Stephen Horne wrote:
>On Tue, 14 Oct 2008 15:58:15 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>>Sorry, but when virtual inheritance is involved, it's
dynamically defined. At least with all of the compilers I know,
and I don't think it's possible to implement it otherwise.

I'm sorry, but it's basic textbook. The compiler determines what is
inherited and places each inherited class at a particualar offset
within the derived class, as if it were member data (which it is).
This isn't true. See 9.2.12 and 10.0.5.
The standard has already been quoted at me, but read James' point that
I was replying too - this isn't about the standard, it's about all the
compilers he knows and what he thinks is possible.

I challenge you. First, define a class using *ANY* standard C++
features you please - multiple inheritance and virtual inheritance
included. Lets call this class TEST.

Now, create two instances of TEST. Don't care where you instantiate so
long as you aren't using any further inheritance - global, local,
normal member, static member, anything. Placement new it if you think
that'll make a difference. Just make sure you don't instance any
derived classes - both must be instances of the exact same class, ie
TEST.

Now, show me a compiler - *ANY* compiler - that uses different memory
layouts for those two instances.

Basic science. The easiest way to prove that instances of a single
class can be arranged differently in different cases is to provide an
example, and I'm only asking for one.

You won't find one. The layout of the class isn't dynamic. It may not
be the same as the layout of any classes that inherit from it, but
that's beside the point. Even multiple inheritance would break offsets
if you're looking at derived classes.

Can you imagine what it would be like if one instance of a class was
arranged differently to another instance of that exact same class? Can
you imagine any vaguely coherent reason why a compiler-writer would
choose to introduce pointless nondeterminism like this?

No - of course not.

Oct 15 '08 #17

P: n/a
On Oct 15, 7:03 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
On Wed, 15 Oct 2008 16:30:54 +1300, Ian Collins
<ian-n...@hotmail.comwrote:
Stephen Horne wrote:
On Tue, 14 Oct 2008 15:58:15 -0700 (PDT), James Kanze
<james.ka...@gmail.comwrote:
Sorry, but when virtual inheritance is involved, it's
dynamically defined. At least with all of the compilers I
know, and I don't think it's possible to implement it
otherwise.
I'm sorry, but it's basic textbook. The compiler determines
what is inherited and places each inherited class at a
particualar offset within the derived class, as if it were
member data (which it is).
This isn't true. See 9.2.12 and 10.0.5.
The standard has already been quoted at me, but read James'
point that I was replying too - this isn't about the standard,
it's about all the compilers he knows and what he thinks is
possible.
I challenge you. First, define a class using *ANY* standard
C++ features you please - multiple inheritance and virtual
inheritance included. Lets call this class TEST.
Now, create two instances of TEST. Don't care where you
instantiate so long as you aren't using any further
inheritance - global, local, normal member, static member,
anything.
You've suddenly introduced some new, unrealistic constraints.
Placement new it if you think that'll make a difference. Just
make sure you don't instance any derived classes - both must
be instances of the exact same class, ie TEST.
Now, show me a compiler - *ANY* compiler - that uses different
memory layouts for those two instances.
Basic science. The easiest way to prove that instances of a
single class can be arranged differently in different cases is
to provide an example, and I'm only asking for one.
I gave one in another posting. You've just said above (for the
first time) that you're not interested in that case. So
offsetof can be made to work, except when it can't.

The standard can't be based on such things. If the standard
says it works, then it has to work.
You won't find one. The layout of the class isn't dynamic.
The layout is dynamic. It depends on the context where the
class is used. You can't get around that by saying you don't
want to consider such contexts.
It may not be the same as the layout of any classes that
inherit from it, but that's beside the point. Even multiple
inheritance would break offsets if you're looking at derived
classes.
Not really. Given a class D, which derives virtually from a
class B, the offsets of elements inherited from B depends on how
D is being used---practically, it depends on which constructor
is called (in g++'s implementation), or which hidden argument is
passed to the constructor (in some other implementations I've
used).
Can you imagine what it would be like if one instance of a
class was arranged differently to another instance of that
exact same class?
I can not only imagine it, I've experienced it.
Can you imagine any vaguely coherent reason why a
compiler-writer would choose to introduce pointless
nondeterminism like this?
It's not nondeterminism, but it does depend on the context in
which the class is used. Given the arguments to offsetof, the
compiler does not have enough information to determine that
context.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 15 '08 #18

P: n/a
On Oct 15, 5:56 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
On Wed, 15 Oct 2008 16:39:32 +1300, Ian Collins <ian-n...@hotmail.com>
wrote:
Stephen Horne wrote:
In my current circumstances, paying for the standard would mean not
eating for a week,
You can live off $18 a week, I'm impressed.
Not quite *that* tight, but 'live' is questionable anyway.
That's not the price I saw for the standard (or the one James
quoted).
I didn't quote an exact price, because I didn't remember it.
But I do recognize that if you don't have a regular job, even
$18 can be a lot. (On the other hand, if you know C++, regular
jobs are pretty easy to come by, at least here in western
Europe. Maybe not always the best jobs in the world, but they
still beat unemployment benefits.)
If that price is available, next problem is no credit card. I
refuse to get one so long as I'm on benefits for obvious
reasons.
A constraint that means C data structure code cannot be
adapted and wrapped in a C++ template? IIRC, one of the
basic design principles of C++ is that people should be
able to adapt their C libraries without a complete rewrite.
By definition, a C data structure is a POD struct, so you can
use offsetof.
template<typename T>
struct This_May_Not_Be_POD
{
T Because_This_May_Not_Be_POD;
};
That's the whole point.
But that' not C; it's C++. And how is it relevant to offsetof?

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 15 '08 #19

P: n/a
On Wed, 15 Oct 2008 01:45:58 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>On Oct 15, 3:06 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
>On Tue, 14 Oct 2008 15:58:15 -0700 (PDT), James Kanze
I'm sorry, but it's basic textbook. The compiler determines
what is inherited and places each inherited class at a
particualar offset within the derived class, as if it were
member data (which it is).

You must be reading the wrong textbooks (or you don't understand
virtual inheritance), since it's provably impossible to do so.
And it's simple to try:
struct VB
....
struct M : virtual VB
....
struct D : M
{
int d ;
} ;
....
M v1 ;
v1.f( std::cout ) ;
D v2 ;
v2.f( std::cout ) ;
return 0 ;
}

I get different values for the two variables with every compiler
I try.
What this proves is that you didn't read my post. You haven't
instantiated two instances of the same class - you have instantiated
two instances of *TWO* *DIFFERENT* *CLASSES*.

Given all your insistence on pedantic language, how can you not notice
that point?

The class M uses virtual inheritance, but it's not a dynamic entity in
itself. It's not a run-time entity at all. It has one layout. It isn't
the same layout that is used for D, even for those components that are
inherited from M, but that's what you get for using virtual
inheritance. As I pointed out elsewhere, even multiple inheritance
breaks offsetof if thats what you're dealing with.

This issue has NOTHING to do with applications which take the
following form...

template<typename T>
struct Node
{
T field_within_node;
};

....

x = offsetof (Node<M>, field_within_node);

Unless you're stupid enough to think the offset also applies to
instances of Node<Dwhich is a DIFFERENT TYPE, just as D is a
DIFFERENT TYPE to M.
>Except that I can prove my statements. Both by example and by
formal proof.
But primarily by failing to read before you reply and obsessing on an
irrelevant issue, which invalidates both so-called proofs.

If you can't read what I post before replying (or is it that you can't
admit to a mistake?), I see no point in reading on.

Oct 15 '08 #20

P: n/a
On Wed, 15 Oct 2008 01:54:32 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>On Oct 15, 7:03 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
>On Wed, 15 Oct 2008 16:30:54 +1300, Ian Collins
<ian-n...@hotmail.comwrote:
>Now, create two instances of TEST. Don't care where you
instantiate so long as you aren't using any further
inheritance - global, local, normal member, static member,
anything.

You've suddenly introduced some new, unrealistic constraints.
How so? In my container library, why would some other code be creating
nodes that inherit my private node type? That would be absurd.

These are the exact constraints I described from the start.

The offsetof is used to pick out the positions of certain fields in a
struct that I control, and placed in a closure-like data block, so
that data-driven non-typesafe code can find those fields. The struct
is defined as a private detail in a thin template wrapper.

Nodes are created. Nodes are accessed. Nodes are modified. Nodes are
destroyed. For any one wrapper class, they are all the same damn node
type - or at worst, minor variants with a shared header.

The node may be non-POD because the type specified by the application
as a template parameter for the contained data may be non-POD. This
*should* be completely irrelevant to offsetof.

Do I need to describe this again?
>I gave one in another posting. You've just said above (for the
first time) that you're not interested in that case.
Crap - you just didn't read it properly.
>The standard can't be based on such things. If the standard
says it works, then it has to work.
>You won't find one. The layout of the class isn't dynamic.

The layout is dynamic. It depends on the context where the
class is used. You can't get around that by saying you don't
want to consider such contexts.
class M isn't class D - they are different classes, irrespective of
the fact that one inherits the other. The layout for either one is
fixed.

As for not considering your irrelevant contexts, what the hell do you
expect. Inheritance has nothing to do with offsetof. To offsetof, any
struct or class is just itself - not a representative of a family.
Just as it always was.

Why the hell should I consider your invented fantasy issues?

Of course if someone is confusing the term "offset" with "member"...

Let me give you a clue. The word offset refers to the layout of the
struct/class. That is *all* it refers to. Any assumptions about that
offset mapping to any particular field in some other struct are
obviously the programmers responsibility, just as they always were,
and I'm not making *ANY* such assumptions. Inheritance would be just
another way to define that some other struct, but no-one gets the
chance to inherit the thing anyway. Any inheritance issues are purely
restricted to fields that takes application specified types, and
frankly should be none of the containers business.

The situation WRT the data structure node is - or at least should be -
exactly the same as it always was, irrespective of non-PODness
propogating up from member field to node struct.
>Can you imagine any vaguely coherent reason why a
compiler-writer would choose to introduce pointless
nondeterminism like this?

It's not nondeterminism, but it does depend on the context in
which the class is used. Given the arguments to offsetof, the
compiler does not have enough information to determine that
context.
No it doesn't, because we are talking about a field within a known
struct, not within an instance of some unknown dynamically-accessed
struct. We always were right from the start. Its all we *could* have
been talking about, since offsetof doesn't know *ANYTHING* about
instances at all - it only ever sees types and field-names.

I only need offsetof to do the basic job that offsetof always did. I
don't need all the overengineered crap that's built into member
pointers, and neither does anyone else. If they had worked when I had
needed them I would have used them anyway, but they didn't.

All I require of offsetof is what it was always meant to do - give me
the offset of a known visible field within the fixed layout of a known
struct. The only "new" C++-specific thing is that the struct might
happen to have non-POD fields (due to app-specified types from
template parameters), and therefore the struct as a whole might happen
to be non-POD for that (and only that) reason.

In practice, of course, it should be perfectly possible to define my
node structs using multiple and virtual inheritance if I feel like it.
It makes no difference in principle - offsetof is still looking for a
known visible field in a known struct with a fixed layout. I wouldn't
*assume* it's possible because I know how the traditional macro form
worked.

But even for that, lets face it - most people would call virtual
inheritance a niche tool at best, and possibly another failed
experiment. What was done is to break offsetof for *all* cases of
non-POD however it arises, just to support virtual inheritance without
tweaking the offsetof implementation or even just stating "not if the
type inherits any virtual base, directly or indirectly" which took me
all of five seconds to write.

By the way, this "never used" offsetof is scattered throughout the
Microsoft libraries like confetti. Also, I popped over to
http://www.koders.com/, but I figured I didn't much feel like
searching through the 1,133 results - on a quick skim, some obviously
aren't genuine uses, but some equally obviously are. That's for C++,
not C.

Genuine uses occur in applications like Blender, in framework code
such as some marshalling stuff, in Boost and more.

Seems like offsetof is used. Not a huge amount of course - but any
"it's not needed because it's not used" argument is pure BS.

Oh, and that Boost example is a container. bidirectional_map to be
specific. And guess what - the offsetof parameter is a type that's
dependent on template parameters, which could easily be non-POD.

Well, I say "that Boost example", but there are several other examples
in Boost. Just pop over to Koders and do a search.

In other words Boost is doing exactly what I do. Wow. Boost
contributors doing precisely the same "no-one does that" thing that I
do. What a shock.
What the hell. You'll never admit to being wrong anyway, so what's the
point.

*PLONK*

Oct 15 '08 #21

P: n/a
On Wed, 15 Oct 2008 01:59:58 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>On Oct 15, 5:56 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
>On Wed, 15 Oct 2008 16:39:32 +1300, Ian Collins <ian-n...@hotmail.com>
wrote:
>Stephen Horne wrote:
>In my current circumstances, paying for the standard would mean not
eating for a week,
>You can live off $18 a week, I'm impressed.
>Not quite *that* tight, but 'live' is questionable anyway.
That's not the price I saw for the standard (or the one James
quoted).

I didn't quote an exact price, because I didn't remember it.
But I do recognize that if you don't have a regular job, even
$18 can be a lot. (On the other hand, if you know C++, regular
jobs are pretty easy to come by, at least here in western
Europe. Maybe not always the best jobs in the world, but they
still beat unemployment benefits.)
That's good - when you can cope with employment. It doesn't help much
when you have a disability that means simply seeing someones face can
trigger an autonomic stress response, simply hearing someones voice
can trigger a stress response, and so on. It doesn't help when that
stress response persists for certainly hours, potentially days, making
any regular sleep and waking pattern impossible.

Aspergers is a disability. Despite what some people think, it doesn't
mean I just don't like people much and don't get invited to parties.
It is a neurologically based disorder with consequences that might
seem trivial in the short term, but the long term repercussions of all
the stress include further brain damage that further deregulates the
stress response and so on.

In short, the Disney attitude dont-give-up-hope crap may be
well-intentioned, but it can still amount to abuse, pushing people
into situations where they end up even more disabled due to the damage
caused by sustained stress.
BTW - I'm not offended by what you said - no reason you should know
this stuff - even most autistics don't know this stuff, and I'm
starting to suspect the experts don't want to know because it would
upset parents, teachers, etc. Anyway, it's my problem, not yours -
just telling it as it is.
What I *want* to do is develop my own projects on my own schedule at
home, self employed. Not working out that way, partly because I can't
see how to make it work. Programming? yes. Target a complete
application to a potential market? Harder - my interests tend toward
internals - but if I have to. But the whole business? - really can't
see that working at all.

I mean, can you imagine my support e-mails? ;-)

Also, then there's the whole
benefits-cancelled-then-the-business-goes-tits-up thing. It took the
best part of a year to get through that crap last time around. It's
not easy when you're too sick to go through the process that proves
that you're sick - but only in phases so they don't really see it.

>template<typename T>
struct This_May_Not_Be_POD
{
T Because_This_May_Not_Be_POD;
};
>That's the whole point.

But that' not C; it's C++. And how is it relevant to offsetof?
It is very relevant when you take the offset of the field
Because_This_May_Not_Be_POD - remembering that this is a simplified
illustrative example.

Boost has code that uses offsetof, including a container that does
exactly this - except that its This_May_Not_Be_POD struct is actually
std::pair.
BTW - The *PLONK* stands, as soon as I set the filter up. After all,
we're both probably better off.

Oct 15 '08 #22

P: n/a
Stephen Horne wrote:
That's good - when you can cope with employment. It doesn't help
much when you have a disability that means simply seeing
someones face can trigger an autonomic stress response, simply
hearing someones voice can trigger a stress response, and so on.
It doesn't help when that stress response persists for certainly
hours, potentially days, making any regular sleep and waking
pattern impossible.
Do you practice a stress-control technique? Autogenic Training and
various kinds of meditation can quite effectively help tame
the autonomic response. And don't think they're only of use to
neurotypicals.

Anyway, there's a software house in Sweden that specifically seeks
ADS sufferers and accomodates them with remote working etc. I can't
manage to seek them out now but I'll ask my source again. Or perhaps
someone else knows who I mean.
Martin

--
Sufficiently encapsulated magic is
indistinguishable from technology.
Oct 15 '08 #23

P: n/a
On Oct 15, 1:33*pm, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
On Wed, 15 Oct 2008 01:54:32 -0700 (PDT), James Kanze
<james.ka...@gmail.comwrote:
On Oct 15, 7:03 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
On Wed, 15 Oct 2008 16:30:54 +1300, Ian Collins
<ian-n...@hotmail.comwrote:
Now, create two instances of TEST. Don't care where you
instantiate so long as you aren't using any further
inheritance - global, local, normal member, static member,
anything.
You've suddenly introduced some new, unrealistic constraints.
How so? In my container library, why would some other code be
creating nodes that inherit my private node type? That would
be absurd.
Who cares about what your container library might do? A
container library has no need of offsetof. We're talking about
why offsetof is not defined and not implementable in the general
case. And in the general case, you have to handle base classes
correctly.
These are the exact constraints I described from the start.
You never described any real constraints. The fact remains that
they are artificial constraints.
The standard can't be based on such things. *If the standard
says it works, then it has to work.
You won't find one. The layout of the class isn't dynamic.
The layout is dynamic. *It depends on the context where the
class is used. *You can't get around that by saying you don't
want to consider such contexts.
class M isn't class D - they are different classes,
irrespective of the fact that one inherits the other.
But the existance of a class M doesn't mean that class D ceases
to exist. And either offsetof( D, x ) returns a correct result,
constant and for all instances of D, or it can't be supported.
The layout for either one is fixed.
The layout of M isn't fixed. It varies depending on how M is
used.
As for not considering your irrelevant contexts, what the hell
do you expect. Inheritance has nothing to do with offsetof.
Agreed. The committee didn't want to open up that hornets'
nest, so they restricted offsetof to PODS. And a PODS cannot
inherit, much less virtually.
To offsetof, any struct or class is just itself - not a
representative of a family. Just as it always was.
Why the hell should I consider your invented fantasy issues?
Because they're real issues, and it's necessary to address them
if you want to support offsetof for non-PODS.
Of course if someone is confusing the term "offset" with
"member"...
Let me give you a clue. The word offset refers to the layout
of the struct/class.
And a class which derives from another class virtually doesn't
have a fixed layout.
Can you imagine any vaguely coherent reason why a
compiler-writer would choose to introduce pointless
nondeterminism like this?
It's not nondeterminism, but it does depend on the context in
which the class is used. *Given the arguments to offsetof,
the compiler does not have enough information to determine
that context.
No it doesn't, because we are talking about a field within a
known struct, not within an instance of some unknown
dynamically-accessed struct.
Exactly. We're talking about a field in M. Whose position
changes depending on how you use M.
We always were right from the start. Its all we *could* have
been talking about, since offsetof doesn't know *ANYTHING*
about instances at all - it only ever sees types and
field-names.
Which is why it is restricted to PODS, which do have constant
offsets, known to the compiler.

[...]
But even for that, lets face it - most people would call
virtual inheritance a niche tool at best,
It's widely used, and vitally necessary for many things.
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 15 '08 #24

P: n/a
On Oct 15, 11:26*am, Stephen Horne <sh006d3...@blueyonder.co.uk>
wrote:
On Wed, 15 Oct 2008 01:45:58 -0700 (PDT), James Kanze
<james.ka...@gmail.comwrote:
On Oct 15, 3:06 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
On Tue, 14 Oct 2008 15:58:15 -0700 (PDT), James Kanze I'm
sorry, but it's basic textbook. The compiler determines
what is inherited and places each inherited class at a
particualar offset within the derived class, as if it were
member data (which it is).
You must be reading the wrong textbooks (or you don't
understand virtual inheritance), since it's provably
impossible to do so. And it's simple to try:
* *struct VB
...
* *struct M : virtual VB
...
* *struct D : M
* *{
* * * *int * * * * * * * * d ;
* *} ;
...
* * * *M * * * * * * * * * v1 ;
* * * *v1.f( std::cout ) ;
* * * *D * * * * * * * * * v2 ;
* * * *v2.f( std::cout ) ;
* * * *return 0 ;
* *}
I get different values for the two variables with every
compiler I try.
What this proves is that you didn't read my post.
What this proves is what I said it proves. That sizeof is not
implementable for certain types.
You haven't instantiated two instances of the same class - you
have instantiated two instances of *TWO* *DIFFERENT*
*CLASSES*.
Do you know any C++ at all? I've definitly got two instances of
M; one in one context, and one that isn't.
Given all your insistence on pedantic language, how can you
not notice that point?
Did you notice that there is an M object in the D? Do you
understand what is meant by a type?
The class M uses virtual inheritance, but it's not a dynamic
entity in itself. It's not a run-time entity at all. It has
one layout.
Which is? It quite obviously has two different layouts in my
code above, depending on whether it is a base class of D or not.
It isn't the same layout that is used for D, even for those
components that are inherited from M, but that's what you get
for using virtual inheritance. As I pointed out elsewhere,
even multiple inheritance breaks offsetof if thats what you're
dealing with.
Not at this level. Modulo access issues and possible
ambiguities, offsetof could be well defined for multiple
inheritance, as long as no virtual inheritance is involved.
This issue has NOTHING to do with applications which take the
following form...
Whether offsetof is implementable for non PODS has nothing to do
with any application. It's a matter of principle: either the
offset is fixed, or it's not. In the case of C++, it's not, at
least when virtual inheritance is involved.
Unless you're stupid enough to think the offset also applies
to instances of Node<Dwhich is a DIFFERENT TYPE, just as D
is a DIFFERENT TYPE to M.
Except that I can prove my statements. *Both by example and
by formal proof.
But primarily by failing to read before you reply and
obsessing on an irrelevant issue, which invalidates both
so-called proofs.
If you can't read what I post before replying (or is it that
you can't admit to a mistake?), I see no point in reading on.
In other words, you've lost the argument, so you're taking your
ball and going home.

I'd suggest you actually learn C++ before trying to criticize
it.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 15 '08 #25

P: n/a
On Oct 15, 2:25*pm, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
On Wed, 15 Oct 2008 01:59:58 -0700 (PDT), James Kanze
<james.ka...@gmail.comwrote:
On Oct 15, 5:56 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
On Wed, 15 Oct 2008 16:39:32 +1300, Ian Collins
<ian-n...@hotmail.comwrote:
Stephen Horne wrote:
In my current circumstances, paying for the standard
would mean not eating for a week,
You can live off $18 a week, I'm impressed.
Not quite *that* tight, but 'live' is questionable anyway.
That's not the price I saw for the standard (or the one
James quoted).
I didn't quote an exact price, because I didn't remember it.
But I do recognize that if you don't have a regular job, even
$18 can be a lot. *(On the other hand, if you know C++,
regular jobs are pretty easy to come by, at least here in
western Europe. *Maybe not always the best jobs in the world,
but they still beat unemployment benefits.)
That's good - when you can cope with employment. It doesn't
help much when you have a disability that means simply seeing
someones face can trigger an autonomic stress response, simply
hearing someones voice can trigger a stress response, and so
on. It doesn't help when that stress response persists for
certainly hours, potentially days, making any regular sleep
and waking pattern impossible.
That's a serious disability, and if it is really that bad, it
pretty much means that you need to consider a different
profession. Programming is a team activity; you can't develop
good programs without working with others, and communicating
with them. Face to face and in writing.
Aspergers is a disability.
I won't argue with that. Although I'm not familiar with this
particular disability. There are lots of different types of
disabilities, and some of the disqualify the person for some
particular types of employ---you don't see many blind taxi
drivers, for example, and that's not because of anything I'd
consider discrimination against the blind. If you're going to
work in programming, not being able to meet and discuss things
with your collegues is a disqualifying disability, whatever its
reasons may be.

[...]
In short, the Disney attitude dont-give-up-hope crap may be
well-intentioned, but it can still amount to abuse, pushing
people into situations where they end up even more disabled
due to the damage caused by sustained stress.
Well, I suspect that there are some cases where you do have to
give up hope. I once had a blind friend who wanted to be a race
car driver. Realistically...

There are, of course, a lot of other things one can do.
BTW - I'm not offended by what you said - no reason you should
know this stuff - even most autistics don't know this stuff,
and I'm starting to suspect the experts don't want to know
because it would upset parents, teachers, etc. Anyway, it's my
problem, not yours - just telling it as it is.
What I *want* to do is develop my own projects on my own
schedule at home, self employed. Not working out that way,
partly because I can't see how to make it work. Programming?
yes. Target a complete application to a potential market?
Harder - my interests tend toward internals - but if I have
to. But the whole business? - really can't see that working at
all.
I mean, can you imagine my support e-mails? ;-)
All of us have our limits; maybe not as serious as yours, but I
tend to avoid support work as well; it doesn't fit me.
template<typename T>
struct This_May_Not_Be_POD
{
* T *Because_This_May_Not_Be_POD;
};
That's the whole point.
But that' not C; it's C++. *And how is it relevant to offsetof?
It is very relevant when you take the offset of the field
Because_This_May_Not_Be_POD - remembering that this is a
simplified illustrative example.
But the purpose of having offsetof in C++ is only backwards
compatibility with C. For all of the known uses of offsetof to
me, C++ has better alternatives.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 15 '08 #26

P: n/a
Stephen Horne <sh********@blueyonder.co.ukkirjutas:
>
This from the guy who just declared that offsetof is only there for C
compatibility, and shouldn't be used.

OK - what's the alternative, then?
As Stephen is not so prone to provide compilable code samples, I will
provide one of my own distilled from working production code. I have no
idea if it bears any resemblance to Stephen's issues, but I think this is
something which could make use of a generalized offsetof() macro. What
the code does is to register the offset of a variable ("parameter") in a
derived class in another dynamic library, and assigning it a value later.

Restrictions:

Derived class must be as simple as possible (there are hundreds of such
classes). When started, Derived::Run() should just find the class member
parameters initialized to needed values.

In this example only one parameter of type 'int' is used. In reality
there are arbitrarily many parameters of multiple (restricted set of)
possible types. The parameter registration involves communicating both
the parameter type and offset, the type (an enum value) omitted here for
brevity. So the parameters cannot be just passed as parameters for the
Run() function.

The Base class and main() do not know anything about the Derived class.

Task:

The ob1 object in line A is actually not used except for finding out the
offsets of parameter data members. Please rewrite the code so that
creation of this dummy object ob1 would not be needed.

The code follows:

// MAIN EXECUTABLE
#include <iostream>

class Base {
public:
Base(): base_data_(111) {}
virtual int Declare()=0;
virtual void Run()=0;
virtual ~Base(){}
protected:
int RegisterInput(void* memberaddr) {
return static_cast<char*>(memberaddr)
- static_cast<char*>(static_cast<void*>(this));
}
private:
int base_data_;
};

typedef Base* (*creator_functype)();
creator_functype RegisterDerived();

int main() {
creator_functype creator = RegisterDerived();

// Find out the offset of param1_ in the Derived class.
Base* ob1 = (*creator)(); //LINE A
int offset = ob1->Declare();
delete ob1;

// Much later, and many times: assign value to param1_ and call Run.
Base* ob2 = (*creator)();
*static_cast<int*>(static_cast<void*>
(static_cast<char*>(static_cast<void*>(ob2))+offse t)) = 42;
ob2->Run();
delete ob2;
}

// MIGHT BE IN A SEPARATE LIBRARY
class Derived: public Base {
public:
virtual int Declare() {
return RegisterInput(&param1_);
}
virtual void Run() {
std::cout << "param1=" << param1_ << "\n";
}
static Base* Create() {return new Derived();}
private:
int param1_;
};
creator_functype RegisterDerived() {return &Derived::Create;}

Oct 15 '08 #27

P: n/a
On 15 Oct 2008 13:57:07 GMT, Martin Eisenberg
<ma**************@udo.eduwrote:
>Stephen Horne wrote:
>That's good - when you can cope with employment. It doesn't help
much when you have a disability that means simply seeing
someones face can trigger an autonomic stress response, simply
hearing someones voice can trigger a stress response, and so on.
It doesn't help when that stress response persists for certainly
hours, potentially days, making any regular sleep and waking
pattern impossible.

Do you practice a stress-control technique? Autogenic Training and
various kinds of meditation can quite effectively help tame
the autonomic response. And don't think they're only of use to
neurotypicals.
Those techniques depend on the link back from the prefrontal cortex to
the amygdala being intact - the link that switches off unnecessary
stress reactions. It's a fragile link. Both the amygdala and the
prefrontal cortex are known damaged in autistic spectrum disorders.

In principle, aromatherapy is about the most likely option to work.
The senses of smell and taste are processed directly in the amygdala,
which is the main autonomic stress response trigger. There's no
guarantee, though, that any smell would make any difference and all I
can say for certain is that I like citrus smells.

The point is that stress control techniques only work if I'm not
really all that stressed anyway. Bear in mind that my really good day
is probably comparable to a normal persons really bad day.

I obsessed with trying to fix myself for decades before finding out
what the problem is. I've tried plenty. What seemed to work in a sense
basically turned out to be a flavor of cognitive behavioural therapy,
but all it was really doing was training me to take on more and more
stress.

The stress response isn't all negative emotions. Think adrenaline
junkie thrills, excitement and mania. Irrespective of whether it feels
good or bad, your brain and body are still running beyond their
sustainable limits and they are still damaging themselves further, and
you are still going to crash and burn. And the next burnout will be
faster and more severe, and so on.
>Anyway, there's a software house in Sweden that specifically seeks
ADS sufferers and accomodates them with remote working etc. I can't
manage to seek them out now but I'll ask my source again. Or perhaps
someone else knows who I mean.
Wouldn't they want people who can speak Swedish?

Oct 15 '08 #28

P: n/a
On Wed, 15 Oct 2008 17:33:04 -0500, Paavo Helde <no****@ebi.eewrote:
>Stephen Horne <sh********@blueyonder.co.ukkirjutas:
>>
This from the guy who just declared that offsetof is only there for C
compatibility, and shouldn't be used.

OK - what's the alternative, then?

As Stephen is not so prone to provide compilable code samples
The following compilable code sample has been provided many times...

template<class T>
struct whatever
{
T field;
};

....

x = offsetof(whatever, field);

For full compilable source, we're talking 7 separate source files with
sizes ranging from about 1000 to about 2500 lines each. Therefore,
descriptions and simplified examples.

I have also provided a reference to a Boost source file that does
basically what I do. Go to www.koders.com and you'll find other
examples. It's not everyday stuff, any more than member pointers or
virtual inheritance, but it's used.
Single inheritance as in your example won't break offsetof in
practice, but IMO it's not the right solution for this.

If any Derived uses Multiple inheritance or virtual inheritance, even
indirectly, offsetof definitely breaks. On some compilers, having
virtual inheritance will cause offsetof to crash immediately (or at
least generate nonsense), since the traditional macro expansion would
end up trying to read the virtual table of a non-existent instance.

OTOH, if Derived is no worse than single inheritance, having fields
that have multiple-inheritance or virtual-inheritance types won't
break it - in practice only - no guarantees from the standard since
your classes are non-POD (even without the inheritance issues from
above).

However, because this depends on users following a rule that the
compiler won't enforce for you, its unsafe. My experience is that
people will forget about that rule.

I'll assume you have good reasons for not making param1 a parameter of
Run.

I'd recommend using pure access functions declared in Base to get at
param1. The virtual call overhead *might* be a problem for you, but
don't optimise until you're sure you need to.

Even if you need to optimise, there are much safer ways to do it. e.g.
You could provide an pure access function in Base that returns a
reference or pointer to the variable within the instance. Then you can
update the buffer as often as you like with minimal cost, so long as
the instance stays put. If there's any possibility that the user might
put the buffer somewhere outside the instance, a lock-and-release
approach might be worthwhile to at least make it explicit that the
buffer is meant to stay put and for how long.

That gives you something like...

BUFFER buffer = obj->lock_buffer ();
// I'll assume exception-for-fail - why nullcheck when most
// implementations will be trivial and infallible.

while (...)
{
*buffer = whatever;
obj->Run ();
}

obj->release_buffer (buffer);

Even if you use a member pointer, the basic principle of converting to
a simple pointer before entering an inner loop still makes sense - and
one advantage if member pointers work for you is that the compiler
will probably do that optimisation for you.

But access functions are the basic workhorse for doing this kind of
thing - member pointers cause too many problems to be practical in my
experience, and offsetof is unsafe if the type of the instance is a
run-time variable.

Oct 16 '08 #29

P: n/a
On Oct 16, 12:33 am, Paavo Helde <nob...@ebi.eewrote:
Stephen Horne <sh006d3...@blueyonder.co.ukkirjutas:
This from the guy who just declared that offsetof is only
there for C compatibility, and shouldn't be used.
OK - what's the alternative, then?
As Stephen is not so prone to provide compilable code samples,
Stephen seems mainly prone to insulting the committee because
they didn't design the language exactly according to his
desires.

The problem is simple: C++ inherited offsetof from C. When
<cstddefwas being defined, the problem of defining what
offsetof meant in C++ (with class types, rather than struct
types) had to be addressed. The simplest solution (in terms of
actual work) was just to limit it to what is basically C: PODS.
Obviously, other solutions are possible, but some restrictions
are necessary. Clearly defining those restrictions is
additional work. Apparently, no one at the time felt it worth
the effort---either they didn't see any important use of
offsetof, or they felt that there were more important things to
do, or whatever. The committee depends on volontary effort, and
no one volonteered to extend offsetof to non-POD types.

All of the rest is really just useless discussion. I don't
particularly see much use of offsetof, and I've written a lot of
low level code. Which explains why I didn't volonteer to do the
work of extending it. The fact that many others working in the
committee apparently felt like me is the real reason why
offsetof isn't defined for non PODS. (The fact that many others
working in the committee -- most of whom are considerably more
competent than I am -- apparently felt like me reassures me.
All too often, I'm in disagreement with a large part of the
committee, which makes me wonder.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 16 '08 #30

P: n/a
Stephen Horne wrote:
Those techniques depend on the link back from the prefrontal
cortex to the amygdala being intact - the link that switches off
unnecessary stress reactions.
The point is that stress control techniques only work if I'm not
really all that stressed anyway.
Of course if you tried it without benefit I can't argue with that.
But I do think that "intact" is too strong a constraint -- it's not a
one-way street, and neither is acute "firefighting" the main point of
practice.

But let's not dwell off topic, I mainly just thought someone might
know that company.
Wouldn't they want people who can speak Swedish?
No. My friend's still digging, though.
Martin

--
Liberty: One of Imagination's most precious possessions.
--Ambrose Bierce
Oct 18 '08 #31

P: n/a
Martin Eisenberg wrote:
Anyway, there's a software house in Sweden that specifically
seeks ASD sufferers and accomodates them with remote working
etc.
In case anyone's interested, the name is Specialisterne.
Martin

--
There are two kinds of people -- those who do the
work and those who take the credit. Try to be in
the first group; there is less competition there.
--Indira Gandhi
Oct 24 '08 #32

P: n/a
Martin Eisenberg wrote:
Martin Eisenberg wrote:
>Anyway, there's a software house in Sweden that specifically
seeks ASD sufferers and accomodates them with remote working
etc.

In case anyone's interested, the name is Specialisterne.
Thanks for the pointer. A very interesting project.
Martin
Schobi
Nov 7 '08 #33

This discussion thread is closed

Replies have been disabled for this discussion.