Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intel C++ compiler bug in member function overload resolution involving "using" alias?

#include <cstddef>

template<typename T, T... Is>
struct Bar { };

template<size_t... Is>
using Baz = Bar<size_t, Is...>;

struct Foo {
  template<size_t... Is>
  void NoAlias(Bar<size_t, Is...>) { }

  template<size_t... Is>
  void Alias(Baz<Is...>) { }
};

template<typename T, T... Is>
void foo(Bar<T, Is...>) { }

template<size_t... Is>
void bar(Bar<size_t, Is...>) { }

int main() {
  // All these work fine
  foo(Bar<size_t, 4, 2>());
  foo(Baz<4, 2>());
  bar(Bar<size_t, 4, 2>());
  bar(Baz<4, 2>());
  Foo().NoAlias(Bar<size_t, 4, 2>());
  Foo().NoAlias(Baz<4, 2>());

  // But these two give error on ICPC (ICC) 14.0.2:
  //   no instance of function template "Foo::Alias" matches the argument list
  // Note the only difference between NoAlias and Alias is (not) using the alias
  // for the member function parameter
  Foo().Alias(Bar<size_t, 4, 2>());
  Foo().Alias(Baz<4, 2>());

  return 0;
}

ICC 14.0.2 gives error:

$ icc -std=c++11 -Wall -pedantic -pthread -o .scratch{-,.}cpp && ./.scratch-cpp

.scratch.cpp(36): error: no instance of function template "Foo::Alias" matches the argument list
            argument types are: (Bar<size_t, 4UL, 2UL>)
            object type is: Foo
    Foo().Alias(Bar<size_t, 4, 2>());
          ^

.scratch.cpp(37): error: no instance of function template "Foo::Alias" matches the argument list
            argument types are: (Baz<4UL, 2UL>)
            object type is: Foo
    Foo().Alias(Baz<4, 2>());
          ^

However, it compiles with both GCC 4.8 and Clang 3.4.2. (Tested on a 64-bit Linux.)

Can anybody who is well acquainted with the C++11 standard confirm this is indeed a bug?

Also, is there an easy preprocessor-based workaround?

like image 469
eold Avatar asked Aug 04 '14 20:08

eold


1 Answers

Your example is (clearly) well-formed. §14.8.2.5/9 describes how deduction is performed in this case.

If P has a form that contains <T> or <i>, then each argument Pi of the respective template argument list P is compared with the corresponding argument Ai of the corresponding template argument list of A. […]. If Pi is a pack expansion, then the pattern of Pi is compared with each remaining argument in the template argument list of A. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by Pi.

Moreover, your code is compiling with version 15.0.3 on my machine. Hence upgrading the compiler should fix the issue. I can't see another simple workaround.

like image 54
Columbo Avatar answered Sep 21 '22 12:09

Columbo