Boost logo

Boost :

Subject: [boost] [polygon] MSVC8 portability and MSVC8 bugs
From: Simonson, Lucanus J (lucanus.j.simonson_at_[hidden])
Date: 2009-07-01 19:50:59

Simonson, Lucanus J wrote:
> Michael Fawcett wrote:
>> On Wed, Jul 1, 2009 at 1:52 PM, Simonson, Lucanus
>> J<lucanus.j.simonson_at_[hidden]> wrote:
>>> Does someone know what specifically is different between MSVC8 and
>>> MSVC9 wrt. SFINAE conformance?  I am shooting in the dark to reverse
>>> engineer the bugs in the compiler that were fixed between MSVC8 and
>>> 9.  There is a good chance that my library won't get backported to
>>> MSVC8 without some guidance from the community.
>> I'm sorry I don't know enough to help out, but both trunk and release
>> test results show that enable_if passes all tests on 7.1, 8.0, 9.0,
>> and 10.0. Are you sure it's a compiler bug?
> Simple cases with enable_if doe work in MSVC8, but as the template
> parameters of enable_if get more elaborate with compile time logic
> metafunctions it breaks down in MSVC8 and not longer seems to work.
> I'm putting together a set of compilation tests that should all pass
> in MSVC9 but some of which fail in MSVC8 to try to empirically
> determine what works and what doesn't with MSVC8.
> I am quite sure it is a compiler bug. Even MSVC9 has severe
> limitations due to a bug that prevents SFINAE from being effective in
> all but top level template instantiation, and the situation is
> apparently worse still with MSVC8 where even in top level
> instantiation SFINAE is not always effective.
> I'll post the results of my testing to share my findings about what
> specifically is broken about SFINAE in MSVC8 that works in MSVC9 once
> the experiments are complete.

It turns out the bug in MSVC8 is much worse than I had feared. I extracted out the minimum subset of code necessary to test the encompass function I showed earlier and MSVC8 dutifully compiled it. I then tried the minimum subset of my own header files necessary to test the encompass function and got a syntax error. Then I started eliminating definitions of unrelated functions from my code until the syntax error disappeared. It turns out that I get a syntax error on my rectangle encompass overloads if my rectangle convolve function is declared before it but not if convolve is declared after. Convolve does not depend on encompass or vis-vera. The relative order of these should be of no consequence since they are unrelated. Changing the order of the declarations of these three functions causes the compilation to succeed, but in the order I declare them compilation fails. If it were just this one overload I'd be able to change the order and sneak past the compiler bug, but this problem impacts dozens of overloaded functions throughout gtl, especially the operators. If the only way to fix it is the change the order of lots of functions that don't depend on eachother it will be practically impossible to find an ordering that doesn't give syntax errors as the number of functions increases. This is because there is no way to reason about what the right order should be, since the behavior of the compiler is inexplicable. I don't believe it is feasible for me to back port to MSVC8. Does anyone see a way around this?


Below is the minimum code snippet required to reproced the syntax error in MSVC8 when compiling in my sandbox gtl/boost/polygon directory:

#include "isotropy.hpp"
#include "rectangle_data.hpp"
#include "point_data.hpp"
#include "point_traits.hpp"
#include "interval_traits.hpp"
#include "rectangle_traits.hpp"
#include "point_concept.hpp"
#include "interval_concept.hpp"
//#include "rectangle_concept.hpp"

namespace boost { namespace polygon {

  struct rectangle_concept{};
  template <typename T>
  struct geometry_concept<rectangle_data<T> > {
    typedef rectangle_concept type;
  template <typename T>
  struct is_mutable_rectangle_concept { typedef gtl_no type; };
  template <>
  struct is_mutable_rectangle_concept<rectangle_concept> { typedef gtl_yes type; };
  template <typename T>
  struct is_rectangle_concept { typedef gtl_no type; };
  template <>
  struct is_rectangle_concept<rectangle_concept> { typedef gtl_yes type; };
  template <typename rectangle_type, typename point_type>
  typename enable_if< typename gtl_and<
          typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
      typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
                       rectangle_type>::type &
  convolve(rectangle_type& rectangle, const point_type& convolution_point);

  template <typename rectangle_type, typename interval_type>
  typename enable_if<
    typename gtl_and<
        typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
        typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
  encompass(rectangle_type& rectangle, const interval_type& b,
            orientation_2d orient) {return true;}

  template <typename rectangle_type_1, typename point_type>
  typename enable_if<
        typename gtl_and<
        typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
        typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
  encompass(rectangle_type_1& rectangle, const point_type& b) {return true;}


int main() {
        using namespace boost;
        using namespace boost::polygon;
        rectangle_data<int> r;
    point_data<int> p;
        encompass(r, p);
        return 0;

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