Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

Compilation failure on template argument pack expansion

Steffen_M_
Beginner
1,498 Views

Hi,

 

I've stumbled across a problem where icpc fails to correctly interpret a template argument list expansion. In particular, the problem occurs when a struct is templated on a variadic template argument list and that list is then expanded into a non-trivial expression like std::shared_ptr<T>... as part of a method signature.

 

Here is a small example:

 

[cpp]

#include <memory>

#include <tuple>

 

template<typename... T>

struct A

{

 

  A(std::shared_ptr<T>... t)

    : _t(t...)

  {}

 

  std::tuple<std::shared_ptr<T>...> _t;

 

};

 

int main()

{

  A<int,double> a(std::make_shared<int>(3),std::make_shared<double>(3.1));

  return 0;

}

[/cpp]

 

Compiling that code works fine on both GCC 4.8.1 and clang 3.4, but fails with ICC (icpc (ICC) 14.0.1 20131008). All compilation was on Linux. The error is:

 

[plain]

$ icpc -std=c++11 parameterpack.cc 

parameterpack.cc(8): error: parameter pack "T" was referenced but not expanded

    A(std::shared_ptr<T>... t)

                      ^

 

parameterpack.cc(8): error: pack expansion does not make use of any argument packs

    A(std::shared_ptr<T>... t)

                        ^

 

parameterpack.cc(18): error: no instance of constructor "A<T...>::A [with T=<int, double>]" matches the argument list

            argument types are: (std::shared_ptr<int>, std::shared_ptr<double>)

    A<int,double> a(std::make_shared<int>(3),std::make_shared<double>(3.1));

                    ^

 

compilation aborted for parameterpack.cc (code 2)

[/plain]

 

If you take out the shared_ptr and just use the plain parameter pack in both the constructor signature and the tuple, ICC manages to compile the code.

0 Kudos
2 Replies
Judith_W_Intel
Employee
1,498 Views

 

Hello Steffan,

I was able to reproduce this bug in 14.0. It has been fixed in our development compiler (which will become our next release).

I have opened a bug report (tracking number DPD200253119) to port this fix back into 14.0 but it's too late to get that into 14.0 update 2 so it will have to wait for update 3.

In the meantime this is a description of the bug:

Spurious error on certain pack expansions in constructor declarations

If a constructor declaration began with a pack expansion where the pack
that was named was not at the top level in the function declarator (e.g.,
in the example below the pack T is not the immediate parameter type but rather
is used inside a template argument list), spurious errors could be issued
about the pack not being expanded and later that the pack expansion did
not make use of any packs.  The errors resulted from the failure to handle
packs in the disambiguation of a constructor declaration, so the error
only occurred when the pack was the first parameter of the constructor.
Now fixed.

  template <typename T> struct A {};
  template <typename... T> struct B {
    B(A<T>... ts);
 };

and based on the description a possible workaround would be to add a dummy first argument to the constructor, i.e.:

#include <memory>
#include <tuple>

template<typename... T>
struct A
{
#ifdef WORKAROUND
 A(int /*dummy*/, std::shared_ptr<T>... t)  // workaround for bug
#else
 A(std::shared_ptr<T>... t)
#endif
    : _t(t...)
  {}
  std::tuple<std::shared_ptr<T>...> _t;
};

int main()
{
#ifdef WORKAROUND
  A<int,double> a(/*dummy=*/0, std::make_shared<int>(3),std::make_shared<double>(3.1));
#else
  A<int,double> a(std::make_shared<int>(3),std::make_shared<double>(3.1));
#endif
  return 0;

}

Sorry for the trouble that this bug has caused you.

Judy

 

 

0 Kudos
Steffen_M_
Beginner
1,498 Views

Hello Judy,

thanks for checking on the issue! We'll be able to work around the problem until the next feature release.

Steffen

0 Kudos
Reply