Boost logo

Boost :

From: Maurizio Vitale (mav_at_[hidden])
Date: 2007-06-21 16:46:29


The following is distilled from a much larger code base and exibits a discrepancy between
gcc 4.2.0 and the Intel C++ compiler 10.0.23 (both under Linux).
GCC compiles the example fine, while the Intel compiler chokes on the last statement, objecting that:

------------------------------ Intel error message ------------------------------
-*- mode: compilation; default-directory: "~/dev/proto_pdl/" -*-
Compilation started at Thu Jun 21 16:34:47

/opt/intel/cce/10.0.023/bin/icpc -I. -obe be.cpp
be.cpp(15): error: class "boost::enable_if<boost::is_same<B, A>, void>" has no member "type"
    struct foo<T, typename boost::enable_if<boost::is_same<X,A> >::type>
                                                                   ^
          detected during instantiation of class "S<X> [with X=B]" at line 24

be.cpp(15): error: class "boost::enable_if<boost::is_same<B, A>, void>" has no member "type"
    struct foo<T, typename boost::enable_if<boost::is_same<X,A> >::type>
                                                                   ^
          detected during instantiation of class "S<X> [with X=B]" at line 24

compilation aborted for be.cpp (code 2)

It seems like the very mechanism on which enable_if is based (SFINAE rule) makes the intel compiler
unhappy. The release notes for version 10 have a fragment that is suspicious:

    New -early-template-check Switch

    Even though recent versions of g++ (3.4 and newer) parse template
    definitions, they do very little semantic checking of such
    definitions. Most of the semantic checking is delayed until an actual
    instantiation is done. As a result, g++ accepts certain unusable
    templates provided they are not actually used in the program. A new
    option is available (-early-template-check) to allow Intel C++ users
    to check the semantics of function template prototypes before
    instantiation.

    Example:

     class A {};
       template <class T> struct B {
         B () {}; // error with -early-template-check): no initializer for
                  // reference member "B<T>::a"
         A& a;
       };

    Note that this switch will work in gcc 3.4 and later compatibility
    modes only (i.e. -gcc-version=340 and later).

This leads me to believe that when not in gcc compatibility mode they
try to be more agressive and analyze template code prematurely (btw,
the code included doesn't compile even with -gcc-version=420).

What is the general opinion on the validity of enable_if w.r.t to
the standard?
Are there known workarounds for the Intel compiler?

Best regards,

     Maurizio

------------------------------ Code ------------------------------
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>

struct A {};
struct B {};

template<typename X>
struct S {

  template<typename T, typename Enable=void> struct foo {
    enum { value=0 };
  };
  
  template<typename T>
  struct foo<T, typename boost::enable_if<boost::is_same<X,A> >::type>
  {
    enum { value=1 };
  };
};

int
main () {
  int i = S<A>::foo<B>::value;
  int j = S<B>::foo<B>::value; // OK for g++ 4.2.0, NOK for Intel C++ 10.0.23
}


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