Boost logo

Boost :

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


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

Boost list run by bdawes at, gregod at, cpdaniel at, john at