Boost logo

Boost :

Subject: Re: [boost] MSVC9 SFINAE quirks?
From: Simonson, Lucanus J (lucanus.j.simonson_at_[hidden])
Date: 2009-01-12 18:19:04


>The difference is that the for literal templates, the compiler does not
>even try to instantiate it. For SFINAE, the compiler has to instantiate >it.
>Basically, the compiler only instantiates what it needs to.

>template<class T>
>typename boost::enable_if<
> boost::mpl::and_<
> a_metafunction<T>, // not instantiated yet
> another_metafunction<T> // not instantiated yet
> >, // not instantiated yet
> some_template<T> // not instantiated yet
> >::type // Now we get some template instantiation
>f(T);
>
>enable_if must be instantiated to get at the ::type.
>enable_if in turn forces instantiation of and_ which forces
>instantiation of one or both of the metafunctions.

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?

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 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.

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?

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.

Thanks again,
Luke


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk