From -2842646463315020485
X-Google-Thread: f78e5,c4ab463952a444d1
X-Google-NewGroupId: yes
X-Google-Attributes: gid7894ca11fe,domainid0,public,usenet
X-Google-Language: ENGLISH,ASCII-7-bit
Path: g2news1.google.com!news2.google.com!Xl.tags.giganews.com!border1.nntp.dca.giganews.com!nntp.giganews.com!local2.nntp.dca.giganews.com!news.giganews.com.POSTED!not-for-mail
NNTP-Posting-Date: Tue, 20 Jul 2010 20:30:05 -0500
Return-Path: <cppmods@ruralroute.cs.rpi.edu>
To: (Usenet)
From: Edward Diener <eldiener@tropicsoft.invalid>
Newsgroups: comp.std.c++
Subject: Re: SFINAE anomaly
Organization: A noiseless patient Spider
Sender: cppmods@cs.rpi.edu
Approved: james.dennett@gmail.com
Message-ID: <i22q9a$ptp$1@news.eternal-september.org>
References: <i1r4g1$uqa$1@news.eternal-september.org>
	<b05afe8b-3962-4bbf-8efc-1ebbc40063d9@t10g2000yqg.googlegroups.com>
	<i1vvqm$2r6$1@news.eternal-september.org>
	<94198f77-7de0-4009-bc94-d41a608bb7ee@w12g2000yqj.googlegroups.com>
Reply-To: eldiener@tropicsoft.com
Content-Type: text/plain; charset=windows-1252; format=flowed
X-Original-Date: Mon, 19 Jul 2010 20:22:59 -0400
X-Submission-Address: std-c++@netlab.cs.rpi.edu
Date: Tue, 20 Jul 2010 20:24:27 CST
Lines: 266
X-Usenet-Provider: http://www.giganews.com
X-Trace: sv3-LET5FdlXcQrUq+mHHgOzVHXaAGmm4Js3/S/9940ixO14Wy74YUUWzewqf2iWW0xTIysMqIqpKYGukUK!w+GfGA4micMLp5MLV4q3RYslzVpzQqXlTTYOMzf5Fn0rfSSCY+2HH2RBIAN8tE4X9pfF
X-Complaints-To: abuse@giganews.com
X-DMCA-Notifications: http://www.giganews.com/info/dmca.html
X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers
X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly
X-Postfilter: 1.3.40
Xref: g2news1.google.com comp.std.c++:2785

On 7/19/2010 7:21 PM, =?ISO-8859-1?Q?Daniel_Kr=FCgler?= wrote:
>
> On 19 Jul., 20:19, Edward Diener<eldie...@tropicsoft.invalid>  wrote:
>>
>> On 7/18/2010 5:27 PM, Daniel Kr=FCgler wrote:
>>
>>> I think this is clearly a compiler defect.
>>
>> Is it a compiler defect under the C++03 compiler using SFINAE, or are
>> you saying it is a compiler defect under the C++0x extended SFINAE ? If
>> it is a compiler defect only under the C++0x extended SFINAE then it is
>> quite possible that the three versions of compilers I have tested this
>> under do not yet implement the C++0x extended SFINAE.
>
> I ignored C++03 in my discussion because you already mentioned
> "extended SFINAE" rules, which are not available within C++03.
> Looking at the C++03 rules I would say that the wording is not
> really clear here. A weak interpretation of 14.8.2/2 would include
> your example, a strong interpretation would not.

Evidently the compilers I used, which were evidently using the C++03
SFINAE rules, flagged the code as a compiler error rather than a
SFINAE allowed substitution failure. The compilers I was using were
VC9, VC10, and the latest Comeau. I do know that VC9 and VC10 have no
claim to using the extended SFINAE rules, since neither mentions it in
their documentation about what's new in the compiler. As far as Comeau
it may be that I needed to turn on a compiler switch for extended
SFINAE. I will check that out. I also now have gcc4.5.0.1 so i will
look at that also.

> The part of the
> wording which can be interpreted to apply is bullet 2:
>
> =97 The specified template arguments must match the template
> parameters in kind (i.e., type, nontype, template), and there must
> not be more arguments than there are parameters; otherwise type
> deduction fails.
>
> The problem with the C++03 wording is that it describes are
> individual deduction failure cases in a long sub-bullet list below
> bullet 3. Your particular situation is not part of the list.
> The difference in C++0x is, that the individual list is gone and
> the rule is no simply that only types (and expressions) in the
> "immediate context" occurring in the function signature (return
> type, parameters) are considered. I described that in a lax
> way as "top-level types".

Unfortunately the individual list is still there in n3092 14.8.2 P8 in
a Note and the meaning of the Note is not very clear. One could assume
that the Note is listing all cases of type deduction failure to which
SFINAE applies or one could assume that the Note is simply giving just
some examples of cases of type deduction failure to which SFINAE
applies but the list is not all-inclusive. I realize this was taken
from the C++03 document, but I think the Note needs to be clarified.

>
>>> The new rules clearly say that a invalid type occurring on top
>>> level has to be silently ignored.
>>
>> The phrase "invalid type occurring on top level" appears to be yours,
>> and not in the working draft for the standard.
>
> Sure, it was just a non-normative description of the normative
> wording that I quoted later.
>
>>> This is essentially satisfied
>>> for your snippet. Situations which are *not* covered, are
>>> those where instantiation errors occur *within* the type - this
>>> doesn't happen here.
>>
>> I admit I was following the topic athttp://
>
> www.boostcon.com/community/wiki/show/ExtendedSFINAE/, and not
>>
>> attempting to understand what the working draft of the C++0x standard
>> says, where my search for SFINAE yielded nothing.
>
> Exactly, similar to my "top-level-type" wording, the term SFINAE does
> not officially exist in the standard, but it nonetheless became a
> non-normative technical term in C++ discussions (and your thread
> title contains this non-normative term as well).
>
>> It is explained at that web page that the one of the differences between
>> the previous way that SFINAE worked is that "the extended SFINAE rules
>> of C++0x generalize SFINAE to work with arbitrary expressions", where I
>> did not think that "typename U1::template M<U2, U3>*" was such an
>> expression; and where it says that:
>>
>> 'There are two classes of errors for which SFINAE still does not apply:
>>
>>     1. If the type-checking failure is due an access violation (e.g., x
>> + y resolves to a private operator+), that error is a "hard" error that
>> does not invoke SFINAE.
>
> Correct (and we don't have it in your example).
>
>>     2. If the type-checking failure occurs within the instantiation of a
>> class template or in the body of a function template, that error is a
>> "hard" error that does not invoke SFINAE.'
>
> Also correct. A simple example for such a "hard error" can be
> constructed, if we change my revised example as follows:
>
> struct A {
>  template<class T>
>  struct M {
>    M(int, T = T()){}
>  };
> };
>
> template<class T1, class T2 = void>
> struct B {
>  template<class U1, class U2>
>  static char test(typename U1::template M<U2>);
>
>  template<class, class>
>  static char (&test(...))[2];
>
>  static const bool value = sizeof(test<T1, T2>(0)) == 1;
>
> };
>
> B<A>  b;
>
> static_assert(!B<A>::value, "Ouch");
>
> This time we might also expect that this should also be well-
> formed, relying on the assumption that a function parameter
> of type void cannot be valid. But this is a error that happens
> "within" A::M<void>  and not at the immediate type occurring
> in the function declaration
>
>  template<class U1, class U2>
>  char test(typename U1::template M<U2>);
>
>> In this case I did not know if the second exception applied because the
>> phrase "within the instantiation of a class template" could or could not
>> apply to the top level matching of template parameters. If I have:
>>
>> template<class X>  struct Y { };
>>
>> and the instantiation of the template with:
>>
>> Y<someType,someOtherType>  z;
>>
>> one could or could not interpret the "within instantiation of the class
>> template" as including the matching of template parameters.
>>>
>>> FCD 14.8.2/7+8:
>
> The point is that the involved type shows up directly in the
> function declaration. My loose "top-level" term was supposed to
> refer to this immediately occurring type.

I understand what you are saying now. I don't think n3092 makes that
completely clear.

> Another good non-SFINAE
> example is this one:
>
> template<typename T>
> struct indirect {
>  typedef typename T::type type;
> };
>
> template<class T>
> struct B {
>  template<class U>
>  static char test(typename indirect<T>::type);
>
>  template<class>
>  static char (&test(...))[2];
>
>  static const bool value = sizeof(test<T>(0)) == 1;
> };
>
> struct S {
>  typedef int type;
> };
>
> static_assert(B<S>::value, "Oops"); // OK
> static_assert(!B<int>::value, "Oops"); // Error
>
> Again, the error occurs "within" the type indirect<int>,
> because type int does not have a member type "type"
> and this is not a "top-level" type error.

Your examples show what you mean quite well.

>
>>> "
>>> 7 The substitution occurs in all types and expressions that are used
>>> in
>>> the function type and in template parameter declarations.[..]
>>
>>> 8 [..] If a substitution results in an invalid type or expression,
>>> type
>>> deduction fails. An invalid type or expression is one that would be
>>> ill-
>>> formed if written using the substituted arguments. [..] Only invalid
>>> types
>>> and expressions in the immediate context of the function type and its
>>> template parameter types can result in a deduction failure. [..]"
>>
>> I don't know how these passages reflect on the extended SFINAE rules. Is
>> a substitution failure as allowed by extended SFINAE exactly the same as
>> a type deduction failure as in 14.8.2 paragraph 8 ?
>
> In fact the unofficial SFINAE term is ruled by a deduction failure.

I was going by SFINAE: Substitution Failure Is Not An Error. That is
why I asked whether the term 'type deduction failure' in 14.8.2 P8 is
equivalent to 'substitution failure' in SFINAE.

>
>> If that is the case I do not find among the possibiklities an attempt to
>> instantiate a class template with the wrong number or wrong type of
>> template parameters.
>
> First, the above quoted general statement of 14.8.2/2 can be referred
> to in C++03. As I said, this is not 100% clear because the following
> individual list does not mention your example.

That was my point.

>
> In C++0x there is no need anymore for an explicit listing. There is
> a single-"catch all" phrase quoted above:
>
> "If a substitution results in an invalid type or expression, type
> deduction fails. An invalid type or expression is one that would
> be ill-formed if written using the substituted arguments."

The catch-all phrase is still pretty general.

>
> The further wording only restricts this to non-access situations
>
> "Access checking is not done as part of the substitution process.
> Consequently, when deduction succeeds, an access error could
> still result when the function is instantiated."
>
> and to types in the "immediate context":
>
> "Only invalid types and expressions in the immediate context
> of the function type and its template parameter types can result
> in a deduction failure."

This is better but I would still argue that the term "immediate
context" needs to be elucidated. I know what you say it means, by your
examples, and I can agree with you since your examples make it clear
what "immediate context" is there. Perhaps I am being unfair in
assuming that "immediate context" is not readily understood, but I
certainly did not understand to what exactly it referred without your
explaining it.

I have a feeling that compiler vendors who do implement the C++0x
extended SFINAE rules may find the wording not specific enough to
their liking also, but maybe I will be proved wrong.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]



