From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28829 invoked by alias); 28 Jun 2012 17:37:34 -0000 Received: (qmail 28588 invoked by uid 22791); 28 Jun 2012 17:37:31 -0000 X-SWARE-Spam-Status: No, hits=-4.3 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00,KHOP_THREADED X-Spam-Check-By: sourceware.org Received: from localhost (HELO gcc.gnu.org) (127.0.0.1) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 28 Jun 2012 17:37:09 +0000 From: "exa7z at live dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/53788] C++11 decltype sfinae static member function check (4.7.1) Date: Thu, 28 Jun 2012 17:37:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: exa7z at live dot com X-Bugzilla-Status: NEW X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated Content-Type: text/plain; charset="UTF-8" MIME-Version: 1.0 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2012-06/txt/msg01898.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53788 --- Comment #4 from exa7z at live dot com 2012-06-28 17:37:08 UTC --- You are correct in noting that even in C++03 g++ behaves like this. I also tried several other examples yesterday that led me to the same result. And I think it is because of the way g++ behaves differently for what it concerns its "vision" of dependent/non-dependent type names in this particular case. The bug submission code was based on this: ======================================================== template static std::true_type check(X*, decltype(T::fun())* = 0); ======================================================== But it was supposed to be the following which compiles everywhere and is indeed correct: (was worn out at the time and while testing I let a T in the place of X by mistake): ======================================================== template static std::true_type check(X*, decltype(X::fun())* = 0); ======================================================== The difference is in using a non - dependent type name within check() for what check() is concerned when T is used in decltype(T::fun()) while the corrected version with X uses a dependent type name in decltype(X::fun()) for what check() is concerned. When check() gets to instantiation, T has already been substituted before X due to it being the dependent type name in has_static<...> and thus the non - dependent name in check(). As such, a compiler will first have to decide whether the type name involved is dependent or not, and since T is the non - dependent type for what check() is concerned. Now, since the static ::fun() is not a valid test{} member, we are trying to feed to decltype an unresolved symbol related to the *non-dependent* type name for what check() is concerned. Therefore, SFINAE cannot even take place because of that, T is the anchor keeping the ship from sailing *when* a compiler does *not* make a distinction between dependent and non-dependent type names in this case. As a note, I believe there is one more source of confusion due to the existance of .fun() as a symbol. The fact that there is a non - static member fun() makes so that the error message we get from the other compilers is that of saying to us that practically we should have used decltype(T().fun()) since they see that a .fun() (NOT ::fun()) exists and deduce that likely we erred in our call syntax... And the dependent / non - dependent type name issue is ignored. Since compilers can make this distinction I do not see why a dependent/non-dependent type name error should not have been raised in this case by *all*. In summary, I believe that g++ is most likely behaving the way it does because it treats both X and T as dependent type names in check() despite they are not (only X is the actual dependent type name for check()) thus allowing SFINAE to take place (aka T is not an anchor anymore!).