mem-initializer-list中的参数包扩展因表达式列表

时间:2018-02-18 08:01:58

标签: c++ c++14

我认为在阅读C++14 standard第12.6.2节“初始化基础和成员”时我会遗漏一些内容,但我无法弄清楚。具体来说,第12.6.2节第1段说mem-initializer可以是mem-initializer-id(表达式-list_opt)或mem-initializer-id braced-init-list,而mem-initializer ...是(至于我可以在12.6.2的其余部分看到一个有效的构造。但是,以下程序另有说明(这意味着我错过了对第1段中的语法施加的进一步约束):

#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.2.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);
}

我的问题是:在C ++ 14标准中特别提到mem-initializer-list中的参数包扩展只能用于mem-initializer的第二种选择?或者,使用第一种替代方案实际上是否可以,但我需要一些语法技巧来避免歧义?

0 个答案:

没有答案