Google Groups Home
Help | Sign in
Revisiting fvali's answer to Andrei's Reiterated Question
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  9 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
John Madsen  
View profile  
 More options Nov 12 1999, 3:00 am
Newsgroups: comp.lang.c++.moderated
From: jmad...@rci.rutgers.edu (John Madsen)
Date: 1999/11/12
Subject: Revisiting fvali's answer to Andrei's Reiterated Question

Since quite a few people have brought up fvali's post ( cf.
http://www.deja.com/=rj/[ST_rn=ap]/getdoc.xp?AN=451759382
) from March 5 responding to Andrei's question about how to determine
whether a class argument of a template has a certain member, I thought I
would take a look at it.  fvali came up with an absolutely brilliant, fully
standard conformant way of coming very close to doing this.  The exact code
that fvali posted won't compile because he has an illegal definition that
appears to be left over from an earlier implementation.  Also, once fixed,
it can only determine whether a class has a specified inner type.  It's
unable to handle member data or member functions.

His code is definitely hard to understand and it's a little more
complicated than it needs to be.  Here's a simpler re-implementation of his
idea:

class unique {};
template<class _Typ, class _Uq = unique >
class key_type_tester : private _Typ
{
        struct nested;
        friend struct nested;
        typedef char (& yes)[1];
        typedef char (& no)[2];
        static no test(_Uq);
        static yes test(...);

};

template< class _Typ, class key_type>
struct key_type_tester<_Typ, key_type>::nested {
        enum { has_key_type= sizeof(test(key_type())) != sizeof(no) };

};

Given this, key_type_tester<T>::nested::has_key_type is a compile time
constant which is true it T has an inner type named key_type and false if
it doesn't (well, almost ...).  The way it works depends on 14.6.1
Paragraph 5 of the standard which is worth requoting here:

5 In the definition of a member of a class template that appears outside
of  the  class  template definition, the name of a member of this tem-
plate hides the name of a template-parameter.  [Example:
          template<class T> struct A {
                  struct B { /* ... */ };
                  void f();
          };

          template<class B> void A<B>::f()
          {
                  B b;  // A's B, not the template parameter
          }
  --end example]

Because the definition of nested occurs outside the class template
definition, any members of the key_type_tester template (which, crucially,
includes all of _Typ's members) which have the name key_type, hide the
template parameter named key_type.  So, in the expression test(key_type()),
it is either unique's constructor being referenced, or an inner type of
_Typ named key_type if one exists.  Since test() is overloaded, one version
accepting unique objects and the other accepting anything else, if _Typ
doesn't have a key_type, "static no test(_Uq)" is referenced, otherwise
"static yes test(...)" is.  Since these two functions return different
sized types, sizeof lets us determine which is actually referenced.

There are (at least) 2 cases where this code will produce compile time
errors:

1.  There is a non-type, non-static member of _Typ named key_type.
2.  There is no default constructor for _Typ's key_type.
3.  There is an inaccessible (private) member of _Typ named key_type.

As far as I can tell (1) is unavoidable.  (2) can be fixed by making
sizeof(unique) effectively unique (e.g. class unique {char u[5431];};) and
then modifying the enum to:
enum { has_key_type= sizeof(key_type) != sizeof(unique) };

The rest of the template apparatus that fvali uses achieves 2 things that
are different than my implementation:

1.  The unique class is a private member of the key_type_tester template.
2.  references to the compile time constant do not need the "nested" scope
modifier.

All of this is helpful, but what is really needed is a way to determine
whether a type has a certain member.  I worked out a way to do this for
member functions, but I now have this horrible suspicion that it is not
standard conformant.  Anyway, here it is since I've already put it together
:-).  

There are two ways to do it.  You can either test for a member function
with a certain name having any signature or for one having a specific
signature.  The following tests code test for the first case:

class A {
public:
        int memfun();

};

template<class _Typ, int dummy = 1 >
class memfun_tester : private _Typ
{
        struct nested;
        friend struct nested;
        typedef char (& yes)[1];
        typedef char (& no)[2];
        static no test(int);
        static yes test(...);

};

template< class _Typ, int memfun >
struct memfun_tester<_Typ, memfun >::nested {
        enum { has_memfun = sizeof(test(memfun)) != sizeof(no) };

};

int main() {
        cout << memfun_tester<A>::nested::has_memfun << endl;
        return 0;

}

To test for a member function with a specific signature, replace the
template class definition with the following:

template<class _Typ, int dummy = 1 >
class memfun_tester : private _Typ
{
        struct nested;
        friend struct nested;
        typedef char (& yes)[1];
        typedef char (& no)[2];
        static no test(...);
        static yes test(int (_Typ::*)());

};

Note that in the second case, dummy must default to a non-zero value
otherwise it will implicitly convert to the member function pointer.

This code works on the Intel Compiler 4.0 (which uses the EDG front-end),
but as I mentioned, I don't think it conforms to the standard.  It depends
on "memfun" referring to a pointer to a member function.  However, the
standard says in 5.3.1p3, "A pointer to a member is only formed when an
explicit & is used and its operand is a qualified-id not enclosed in
parentheses."  This sounds pretty unequivocal :(.  Many compilers, it
seems, do not conform on this point, but, obviously, that's not something
that can be trusted.  If it doesn't work then this name hiding technique
cannot be used to determine whether a class has certain member functions.
I think that I can actually prove this, but I'm tired of typing at the
moment :).  (Note that the type member test still works - except in the odd
cases I've mentioned).

Hope this helps -- and if anyone has any ideas, please post them.

John Madsen

jmadsen at rci dot rutgers dot edu

      [ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andrei Alexandrescu  
View profile  
 More options Nov 14 1999, 3:00 am
Newsgroups: comp.lang.c++.moderated
From: "Andrei Alexandrescu" <andrewa...@hotmail.com>
Date: 1999/11/14
Subject: Re: Revisiting fvali's answer to Andrei's Reiterated Question
John Madsen <jmad...@rci.rutgers.edu> wrote in message

news:382f67af.1293831471@news.supernews.com...

> fvali came up with an absolutely brilliant, fully
> standard conformant way of coming very close to doing this.

I second you on this. And I think the same about yourself.

[snip]

> 2.  There is no default constructor for _Typ's key_type.

This is easy to dodge. Let's change your code like the following.
Along the way, we get rid of the unique class:

template<class _Typ, class _Uq = int>
class key_type_tester : private _Typ
{
    struct nested;
    friend struct nested;
    typedef char (& yes)[1];
    typedef char (& no)[2];
    static no test(int*);
    static yes test(...);

};

template< class _Typ, class key_type>
struct key_type_tester<_Typ, key_type>::nested {
    enum { has_key_type= sizeof(test((key_type*)0)) != sizeof(no) };

};

I take advantage that the type 'int' lacks a key_type member :o).

The code became a bit even easier to understand. I think this is a
breakthrough in what one can do with C++. It brings a bit of
introspection at compile time possible, which wasn't even considered
possible until now. I also think that techniques based upon
overloading, sizeof, and char[1] and char[2] are going to become
common in the next century (ahem). They have a lot of uses you
wouldn't think of.

Ok, now we've got the ability to find out whether an arbitrary class
has a member type of a given name. What are we going to do with
this?... :o)

Andrei

      [ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
John Madsen  
View profile  
 More options Nov 15 1999, 3:00 am
Newsgroups: comp.lang.c++.moderated
From: jmad...@rci.rutgers.edu (John Madsen)
Date: 1999/11/15
Subject: Re: Revisiting fvali's answer to Andrei's Reiterated Question

"Andrei Alexandrescu" <andrewa...@hotmail.com> wrote:
>John Madsen <jmad...@rci.rutgers.edu> wrote in message
>news:382f67af.1293831471@news.supernews.com...
>> fvali came up with an absolutely brilliant, fully
>> standard conformant way of coming very close to doing this.

>I second you on this. And I think the same about yourself.

That's very flattering, but fvali did the real work :).

This will certainly get around the compile time error, but you will get a
false negative in the case where _Typ's key_type is actually an int.  This
may or may not be a problem depending on the problem at hand.  Also,
nowhere does this code depend on key_type either being or not being a
member of int as far as I can tell.

>The code became a bit even easier to understand. I think this is a
>breakthrough in what one can do with C++. It brings a bit of
>introspection at compile time possible, which wasn't even considered
>possible until now. I also think that techniques based upon
>overloading, sizeof, and char[1] and char[2] are going to become
>common in the next century (ahem). They have a lot of uses you
>wouldn't think of.

>Ok, now we've got the ability to find out whether an arbitrary class
>has a member type of a given name. What are we going to do with
>this?... :o)

I agree.  I think fvalia has hit on something that could be useful in ways
we have yet to realize.  However, unless there is portable way of
determining whether a type has a certain member function, I'm not sure how
useful all of this will be.  That's why I'm holding out for finding
something in the standard that contradicts 5.3.1p3 -- it wouldn't be the
first contradiction in the standard :).  I think there must be because
every compiler I've tried (now including KAI C++) will convert an
unqualified member function name into a pointer to member function within
class scope.  I'm hoping a standard guru can clear this up :).

John Madsen

jmadsen at rci dot rutgers dot edu

      [ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ivan J. Johnson  
View profile  
 More options Nov 15 1999, 3:00 am
Newsgroups: comp.lang.c++.moderated
From: "Ivan J. Johnson" <iva...@my-deja.com>
Date: 1999/11/15
Subject: Re: Revisiting fvali's answer to Andrei's Reiterated Question
In article <382f27a7.168342...@news.supernews.com>,
  jmad...@rci.rutgers.edu (John Madsen) wrote:
[...]

> I agree.  I think fvalia has hit on something that could be useful in
ways
> we have yet to realize.  However, unless there is portable way of
> determining whether a type has a certain member function, I'm not
sure how
> useful all of this will be.  That's why I'm holding out for finding
> something in the standard that contradicts 5.3.1p3 -- it wouldn't be
the
> first contradiction in the standard :).  I think there must be because
> every compiler I've tried (now including KAI C++) will convert an
> unqualified member function name into a pointer to member function
within
> class scope.  I'm hoping a standard guru can clear this up :).

I tried the code from your previous post on several compilers, with
limited success (details below).  For another approach to this problem,
see my posting "Name hiding and dependent bases" from Nov. 12, archived
at
http://x37.deja.com/[ST_rn=md]/threadmsg_md.xp?thitnum=59&mhitnum=0&CONT
EXT=942698462.658178048&new=0

I'm still hoping for a response to my posting, but at this point the
correctness of my code has not been resolved.  If it is in fact
correct, then it could be used to get much the same effect as your
code.  In particular, you could write a global template function with
some default behavior, then optionally "override" it with a member
template providing "specialized" behavior which propagates to derived
classes.  You could also compare typeof(foo<T>) with typeof(::foo<T>)
and use the boolean result to drive partial specializations.

Anyway, I made a few additions to your code so I could compile and test
it:

#include <iostream>
using namespace std;

class A {
public:
        int memfun();

};

class B {};

template<class _Typ, int dummy = 1 >
class memfun_tester : private _Typ
{
        struct nested;
        friend struct nested;
        typedef char (& yes)[1];
        typedef char (& no)[2];
        static no test(int);
        static yes test(...);

};

template< class _Typ, int memfun >
struct memfun_tester<_Typ, memfun >::nested {
        enum { has_memfun = sizeof(test(memfun)) != sizeof(no) };

};

int main() {
        cout << memfun_tester<A>::nested::has_memfun << endl;
        cout << memfun_tester<B>::nested::has_memfun << endl;
        return 0;

}

I tried it on Intel 4.0 and got the desired result:
1
0

OTOH, on gcc 2.95, the output was
0
0

MSVC 6 wouldn't compile it at all (no surprise there).  Neither would
Metrowerks CW 5.0.  Here's the output from Metrowerks:

### MWCC.EXE Compiler:
#    File: unqualptrtomember.cpp
# ------------------------------
#      23:  struct memfun_tester<_Typ, memfun >::nested {
#   Error:                                              ^
#   struct/union/enum/class tag 'memfun_tester' redefined
### MWCC.EXE Compiler:
#      24:   enum { has_memfun = sizeof(test(memfun)) != sizeof(no) };
#   Error:                                         ^
#   undefined identifier 'test'
### MWCC.EXE Compiler:
#      25:  };
#   Error:   ^
#   illegal template declaration
### MWCC.EXE Compiler:
#      28:   cout << memfun_tester<A>::nested::has_memfun << endl;
#   Error:                                     ^^^^^^^^^^
#   undefined identifier 'memfun_tester<A, 1>::nested::has_memfun'
### MWCC.EXE Compiler:
#      29:   cout << memfun_tester<B>::nested::has_memfun << endl;
#   Error:                                     ^^^^^^^^^^
#   undefined identifier 'memfun_tester<B, 1>::nested::has_memfun'

Since only one of the four compilers successfully processed your code
and produced the desired answer, this tends to confirm that your
interpretation of 5.3.1p3 is correct and that there is no loophole by
which a pointer to member may be formed from an unqualified name.

--
Regards,
Ivan J. Johnson
Sacramento, CA

Sent via Deja.com http://www.deja.com/
Before you buy.

      [ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
John Madsen  
View profile  
 More options Nov 17 1999, 3:00 am
Newsgroups: comp.lang.c++.moderated
From: jmad...@rci.rutgers.edu (John Madsen)
Date: 1999/11/17
Subject: Re: Revisiting fvali's answer to Andrei's Reiterated Question
"Ivan J. Johnson" <iva...@my-deja.com> wrote:

Your message slipped by me -- glad you pointed it out.  I will respond in a
moment :).

Seems the only additions are the first two lines, which I did include when
I compiled mine.

>I tried it on Intel 4.0 and got the desired result:
>1
>0

Me too.

>OTOH, on gcc 2.95, the output was
>0
>0

This is definitely incorrect behavior. See below.

If this is how Metrowerks responds to the code, then it has big problems
that have nothing to do with 5.3.1p3 of the standard.  It doesn't seem to
be able to recognize that line 23 is a definition of the template's member
class "nested" rather than a redefinition of the template itself.  This is
as bad as, if not worse than, MSVC.

>Since only one of the four compilers successfully processed your code
>and produced the desired answer, this tends to confirm that your
>interpretation of 5.3.1p3 is correct and that there is no loophole by
>which a pointer to member may be formed from an unqualified name.

None of the compilers that failed failed for the right reason so I don't
take this as sign about the existence or non-existence of the loopphole.

The error (or at least warning) that I would expect based on 5.3.1p3 would
occur here:

template< class _Typ, int memfun >
struct memfun_tester<_Typ, memfun >::nested {
        enum { has_memfun = sizeof(test(memfun)) != sizeof(no) };
                                    ^^^^^^
when the template is instantiated with _Typ equal to a type that has a
public or protected member function named memfun.  The error should be
something like that it cannot convert "memfun" to a pointer to a member
function or that it is an invalid use memfun in some way.  I have yet to
find a compiler that actually gives such an error or warning.

gcc's behavior suggests not that there is no loophole or that my
interpretation of 5.3.1p3 is wrong, but that it doesn't conform to 14.6.1p5
which is the paragraph fvali pointed out that got all of this started :).

John Madsen

jmadsen at rci dot rutgers dot edu

      [ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Lisa Lippincott  
View profile  
 More options Nov 17 1999, 3:00 am
Newsgroups: comp.lang.c++.moderated
From: Lisa Lippincott <lisa_lippinc...@bigfix.com>
Date: 1999/11/17
Subject: Re: Revisiting fvali's answer to Andrei's Reiterated Question
John Madsen <jmad...@rci.rutgers.edu> simplifies fvali's code:

I'm frightened by the prospect that this code could work.  While I like
the idea of introspection, the mechanism behind this code would more
often manifest itself as a trap.  Consider:

template < class A, class B >
class DeriveWithBuffer: public A
  {
   private:
      unsigned char buffer[ sizeof(B) ];

      void ZeroBuffer()
        {
         memset( buffer, 0, sizeof(B) );
        }
   [...]
  };

Everything here works as expected.  But if the definition of ZeroBuffer
is moved outside the class:

template < class A, class B >
void DeriveWithBuffer<A,B>::ZeroBuffer()
  {
   memset( buffer, 0, sizeof(B) );
  }

Here B may refer to a type nested in A, rather than the template parameter.
That change seems dangerous to me.

                                                --Lisa Lippincott

      [ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
John Madsen  
View profile  
 More options Nov 18 1999, 3:00 am
Newsgroups: comp.lang.c++.moderated
From: jmad...@rci.rutgers.edu (John Madsen)
Date: 1999/11/18
Subject: Re: Revisiting fvali's answer to Andrei's Reiterated Question

Lisa Lippincott <lisa_lippinc...@bigfix.com> wrote:
>I'm frightened by the prospect that this code could work.  While I like
>the idea of introspection, the mechanism behind this code would more
>often manifest itself as a trap.  Consider:

[ trap snipped ]

Yes, I agree that the "feature" described in 14.6.1p5 can have odd, and
except in this introspection case, unwanted effects.  I can't figure out
why this in the standard unless, although I think this is very unlikely, it
was to allow something like what fvali has proposed.  I would love to hear
from anyone who knows what it's doing there.

John Madsen

jmadsen at rci dot rutgers dot edu

      [ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ivan J. Johnson  
View profile  
 More options Nov 19 1999, 3:00 am
Newsgroups: comp.lang.c++.moderated
From: "Ivan J. Johnson" <iva...@my-deja.com>
Date: 1999/11/19
Subject: Re: Revisiting fvali's answer to Andrei's Reiterated Question
In article <3834dcfb.280298...@news.supernews.com>,
  jmad...@rci.rutgers.edu (John Madsen) wrote:

Those, and also class B so I could have a negative test as well as a
positive one.

Ah, you're right, there doesn't seem to be anything wrong with the code
Metrowerks is complaining about.  The error message from MSVC was
equally pointless:

...\unqualptrtomember.cpp(28) : error C2027: use of undefined type
'nested'
...\unqualptrtomember.cpp(14) : see declaration of 'nested'
...\unqualptrtomember.cpp(28) : error C2065: 'has_memfun' : undeclared
identifier
...\unqualptrtomember.cpp(29) : error C2027: use of undefined type
'nested'
...\unqualptrtomember.cpp(14) : see declaration of 'nested'

So, no conclusion can be drawn from the fact that Metrowerks and MS
rejected the code.

You're assuming that a 'memfun' defined as a member of some base class
of memfun_tester is allowed to hide 'int memfun' the template
parameter.  It seems to me that the whole question of the validity of
fvali's code revolves around whether the Standard actually requires
this to happen.  Certainly if 'memfun' were defined as a member of
memfun_tester itself, then the member memfun would hide the template
parameter memfun under 14.6.1p5.  A member of a base class is
implicitly also a member of derived classes, so fvali argued that
14.6.1p5 applies to base-class members as well.  On the other hand, the
Standard also contains language, particularly in 14.6.2p5, which
prohibits base-class members from intruding into derived template
classes in such potentially surprising ways, and it is arguably a
defect in the Standard if there is a loophole in that language.  I
think the question of whether fvali's code is good remains open.

If the base memfun is not allowed to hide the template parameter
memfun, then gcc would be correct in accepting the code above, in
always assuming that 'memfun' refers to the template parameter, and in
producing the output it produces.  In other words, the fact that it
doesn't report an error does not imply that it is actually taking the
address of a member as you want.

> I have yet to
> find a compiler that actually gives such an error or warning.

> gcc's behavior suggests not that there is no loophole or that my
> interpretation of 5.3.1p3 is wrong, but that it doesn't conform to
14.6.1p5
> which is the paragraph fvali pointed out that got all of this started

:).

--
Regards,
Ivan J. Johnson
Sacramento, CA

Sent via Deja.com http://www.deja.com/
Before you buy.

      [ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
fvali  
View profile  
 More options Nov 30 1999, 3:00 am
Newsgroups: comp.lang.c++.moderated
From: fvali <fv...@kumc.edu>
Date: 1999/11/30
Subject: Re: Revisiting fvali's answer to Andrei's Reiterated Question

John Madsen wrote:

<snip>

> Yes, I agree that the "feature" described in 14.6.1p5 can have odd, and
> except in this introspection case, unwanted effects.  I can't figure out
> why this in the standard unless, although I think this is very unlikely, it
> was to allow something like what fvali has proposed.  I would love to hear
> from anyone who knows what it's doing there.

> John Madsen

Hiya John,
    I don't really know what that paragraph is doing there but after
orignally discussing this problem with Andrei, the more i had thought
about it the less I felt that any solution based on 14.6.1p5 is really
guaranteed to work.  I would have posted my thoughts on this much sooner
- but I was unaware there was any further discussion (and there wasn't
for the longest time when I actively followed this group) on this topic
till I encountered this thread.

Here is my reasoning (which I hope is flawed ;-)) -
14.6.2.1 says -
[temp.dep.type]
14.6.2.1 Dependent types
1 A type is dependent if it is
— a template parameter,
— a qualified­id with a nested­name­specifier which contains a
class­name that names a dependent type or
whose unqualified­id names a dependent type,
— a cv­qualified type where the cv­unqualified type is dependent,
— a compound type constructed from any dependent type,
— an array type constructed from any dependent type or whose size is
specified by a constant expression
that is value­dependent,
— a template­id in which either the template name is a template
parameter or any of the template argu­ments
is a dependent type or an expression that is type­dependent or
value­dependent.

The only way key_type will be unbound and looked up at the point of the
template instantiation (14.6.4.1) in both the context of the template
definition and the context of the point of instantiation is if
'key_type' is considered a template parameter, right?

If its lookup is not posponed then it must be bound in the definition
context, right? Which means it would have to be an error if not found in
the definition context - without any instantiation of templates.

If 'key_type' is considered a template parameter and its lookup is
postponed till the point of instantiation, it seems 'screwed up' (sorry
for getting all technical) that upon look up at the point of
instantiation 'key_type' will not be considered a template parameter and
will now be bound to a member of a base class of our instantiated
template class.

Also, keep in mind that 14.6.1p5 is in a section that discusses locally
declared names within templates.

Therefore :
template<class T> struct S
{
   struct A; // locally declares A

};

So A is a local declaration within the class template S and is subject
to the rules of 14.6.1
but what about

struct I
{
   struct A;  // Note: not declared in a template

};

template<class T> struct S : T { };

In S<I> can 'A' be considered a locally declared name?

Anyway I find this all fairly unclear.  What do you folks think of all
this?

I hoped some of the C++ gurus would post a definitive answer resolving
this issue, or someone would log a defect report - but if this has been
done, I have missed it.

regards,
-fais

      [ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google