我认为在阅读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的第二种选择?或者,使用第一种替代方案实际上是否可以,但我需要一些语法技巧来避免歧义?