https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84464

            Bug ID: 84464
           Summary: Pack expansion in mem-initializer-list with
                    expression-list
           Product: gcc
           Version: 7.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: tadeus.prastowo at unitn dot it
  Target Milestone: ---

I am referring to C++14 standard
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf) for the
following problem.  Section 12.6.2 "Initializing bases and members" paragraph 1
says that mem-initializer can either be mem-initializer-id(expression-list_opt)
or mem-initializer-id braced-init-list, and mem-initializer... is a valid
construct.  But, GCC rejects the first alternative of the valid construct but
accepts the second alternative of the valid construct as demonstrated by the
following program.  Since both alternatives are valid constructs, GCC shall
accept the first alternative as well.

GCC cannot compile the following program (cf. https://godbolt.org/g/QWj5Q3),
but Clang can (cf. https://godbolt.org/g/jA7Z8H).  I use flag `-std=c++14'.

#include <cstdio>

struct C1 {
  bool a;
  float b;
  C1(bool x, float y) : a(x), b(y) {}
};
struct C2 {
  bool c;
  float d;
  C2(bool x, float y) : c(x), d(y) {}
};
struct C3 {
  bool e;
  float f;
  C3(bool x, float y) : e(x), f(y) {}
};

template<class... baseclasses>
struct A : public baseclasses...
{
  template<class... Ts> A(Ts... args) : baseclasses(args...)... {
    // This uses mem-initializer-id(expression-list_opt).
    // Section 5.2 par 1 says that expression-list is initializer-list.
    // Section 8.5 par 1 says that initializer-list can be
    //     initializer-clause... with initializer-clause being
    //     assignment-expression.
    // Section 5.17 par 1 says that assignment-expression can boil down
    //     to an identifier, for example, args.
    // So, the construct is valid as far as I can see.  But,
    // g++ 5.4.1 fails with: invalid use of pack expansion expression.
    // g++ 7.3.0 fails with: no matching function for call to
    //     ‘C1::C1(bool)’.
    // The fix is to use mem-initializer-id braced-init-list as in:
    //     : baseclasses{args...}...
  }
};

int main() {
  A<C1, C2, C3> a(true, 1.0F);
  std::printf("%d %f %d %f %d %f\n", a.a, a.b, a.c, a.d, a.e, a.f);
}

Reply via email to