473,732 Members | 2,210 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Template technicality - What does the standard say?


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
32 2726
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
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
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
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 objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 13 '08 #5
On Mon, 13 Oct 2008 12:38:51 GMT, Gianni Mariani
<gi*******@mari ani.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
On Mon, 13 Oct 2008 10:08:32 -0700 (PDT), James Kanze
<ja*********@gm ail.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
On Oct 14, 4:58 am, Stephen Horne <sh006d3...@blu eyonder.co.ukwr ote:
On Mon, 13 Oct 2008 10:08:32 -0700 (PDT), James Kanze
<james.ka...@gm ail.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_offs etof( 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 "establishe d 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 objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 14 '08 #8
On Oct 14, 4:08 am, Stephen Horne <sh006d3...@blu eyonder.co.ukwr ote:
On Mon, 13 Oct 2008 12:38:51 GMT, Gianni Mariani
<gi4nos...@mari ani.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 objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 14 '08 #9
Stephen Horne wrote:
On Tue, 14 Oct 2008 01:34:49 -0700 (PDT), James Kanze
<ja*********@gm ail.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

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

Similar topics

6
1529
by: Dave Theese | last post by:
Please see questions in the code below... Thanks! #include <iostream> using namespace std; class foo_class { public: foo_class() {cout << "Constructing..." << endl;}
6
2018
by: Dave | last post by:
Hello all, Consider this function template definition: template<typename T> void foo(T) {} If foo is never called, this template will never be instantiated. Now consider this explicit instantiation of foo:
6
2158
by: Nobody | last post by:
This is sort of my first attempt at writing a template container class, just wanted some feedback if everything looks kosher or if there can be any improvements. This is a template class for a binary search tree. Note there is a requirement for this to be a Win32/MFC "friendly" class, thus the use of CObject and POSITION. There is also a requirement for there not to be a separate iterator class. template <class TYPE, class ARG_TYPE =...
1
2220
by: Kai-Uwe Bux | last post by:
Hi folks, I would like to know which clause of the standard rules out this: template < typename eval > struct recursive_template { typedef typename eval::enum_type Enum;
19
2560
by: n.torrey.pines | last post by:
I have the following tree definition: template<typename T> struct tree { T first; vector<tree<T second; // branches }; which compiles successfully. What I'd like to do though is to use another template like 'pair', because I might have a bunch of useful
272
14108
by: Peter Olcott | last post by:
http://groups.google.com/group/comp.lang.c++/msg/a9092f0f6c9bf13a I think that the operator() member function does not work correctly, does anyone else know how to make a template for making two dimensional arrays from std::vectors ??? I want to use normal Array Syntax.
11
1408
by: Juha Nieminen | last post by:
I'm writing an STL-style data container, and this problem is puzzling me. The following code should demonstrate the problem: //---------------------------------------------------------- #include <iostream> #include <list> template<typename T> class MyClass {
4
1735
by: danilo.turina | last post by:
Hi all, today I encountered a problem that I'm only able to solve by using reinterpret_cast (and I'd like to avoid it). This was my code until yesterday (omitting includes, "using namespace" and the like): ----------------------------------------- // ABC Table struct Table {
2
6641
by: Clyde | last post by:
Hi, what i'm trying to do is: /////////////// Code Start template <class TType, int* p = 0> class Template { public:
0
8774
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9447
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9307
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
6735
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6031
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4550
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3261
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2721
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2180
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.