Subject: Re: [boost] MSVC9 SFINAE quirks?
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2009-01-12 19:26:07


AMDG

Simonson, Lucanus J wrote:
> Maybe I shouldn't have used the word literal. It is a constant looked up by metafunction, of course.
>
> I was talking about different possible implementations for enable_if having different behaviors when compiled in MSVC.
>
> I don't know, but I would guess that the order of evaluation of template parameters separated by the comma operator is not defined by the standard?
>

I believe not.

> A syntax error in the instantiation of some_template<T> might lead the compilation to fail before trying to instantiate and_, I don't know. It seems that this is the case with MSVC some of the time.
>

The point is that the compiler doesn't know that some_template<T> needs
to be instantiated
until after it has gone through the SFINAE. I know that earlier
versions of msvc would sometimes
instantiate templates too soon, but I don't know

> The boost implementation of enable_if works well with MSVC. The alternative 1:
>
> template <typename T, tyepname T2>
> struct enable_if_T { typedef T2 type; };
> template <typename T2>
> struct enable_if_T<false_type, T2> {};
>
> does not behave as expected (and as in gcc) when parsed by MSVC.
>
> The alternative 2:
>
> template <typename T, tyepname T2>
> struct enable_if_T {};
> template <typename T2>
> struct enable_if_T<true_type, T2> { typedef T2 type; };
>
> results in yet another behavior from MSVC, specifically the problem above, whereas alternative 1 resulted in ambiguous function syntax errors in many cases rather than the expected SFINAE overloading semantic.
>
> Boost's implementation of enable_if:
>
> template <typename T, typename T2>
> struct enable_if : enable_if_c<T::value, T2> {};
>
> converts it from a template on type to a template on the constant specified by value. This seems to impact the order of template instantiation as well as the assumptions MSVC makes about whether SFINAE should apply.
>

It's really a case of msvc taking SFINAE too far. If you only have a
single function template,
you can either get an ICE or bizarre runtime behavior. At the moment, I
can't reproduce your
problem, nor can I reproduce the ICE...

> All three work equivalently in gcc (up to the point one would expect them to) from what I can observe. Is gcc being overly generous about what it allows to compile, or is MSVC falling short of what the standard says it should allow?
>

There is not doubt that this is an msvc compiler problem.

> Obviously, I wouldn't have these troubles if I had just used boost::enable_if from the outset, but I don't want to be given a fish, I want to learn to fish.
>

As far as I can tell the only way to get sane behavior is to put
enable_if at the top level. In the attached test, if USE_WRAP == 1
there will be either a compile error or an internal placeholder type
will be printed at runtime. If USE_WRAP == 0, then everything works.
The other flags seem to have no effect.

In Christ,
Steven Watanabe