[Bug c++/53788] C++11 decltype sfinae static member function check (4.7.1)

exa7z at live dot com gcc-bugzilla@gcc.gnu.org
Thu Jun 28 17:37:00 GMT 2012


--- 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<typename X>
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<typename X>
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!).

More information about the Gcc-bugs mailing list