C++ mem初始值设定项列表中的参数包扩展与表达式列表一起失败
在阅读第12.6.2节“初始化基础和成员”时,我想我遗漏了一些东西,但我一直没有弄清楚。具体而言,第12.6.2节第1段规定,mem初始值设定项可以是mem初始值设定项id(表达式列表_opt)或mem初始值设定项id加括号的初始值列表,并且mem初始值设定项。。。是(就我在12.6.2的其余部分所见)一个有效的构造。但是,以下程序显示了其他情况(这意味着我错过了第1段中对语法施加的进一步限制):C++ mem初始值设定项列表中的参数包扩展与表达式列表一起失败,c++,c++14,C++,C++14,在阅读第12.6.2节“初始化基础和成员”时,我想我遗漏了一些东西,但我一直没有弄清楚。具体而言,第12.6.2节第1段规定,mem初始值设定项可以是mem初始值设定项id(表达式列表_opt)或mem初始值设定项id加括号的初始值列表,并且mem初始值设定项。。。是(就我在12.6.2的其余部分所见)一个有效的构造。但是,以下程序显示了其他情况(这意味着我错过了第1段中对语法施加的进一步限制): #包括 结构C1{ 布尔a; 浮球b; C1(boolx,floaty):a(x),b(y){}
#包括
结构C1{
布尔a;
浮球b;
C1(boolx,floaty):a(x),b(y){}
};
结构C2{
布尔c;
浮动d;
C2(boolx,floaty):c(x),d(y){}
};
结构C3{
布尔e;
浮动f;
C3(boolx,floaty):e(x),f(y){}
};
模板
结构A:公共基类。。。
{
模板A(Ts…args):基类(args…){
//这使用mem初始值设定项id(expression-list_opt)。
//第5.2节PAR 1表示表达式列表是初始化列表。
//第8.5节PAR 1表示初始化列表可以是
//初始值设定项子句…初始值设定项子句为
//赋值表达式。
//第5.17节PAR 1表示赋值表达式可以煮沸。
//指向标识符,例如args。
//就我所见,这个结构是有效的,但是,
//g++5.4.1失败:包扩展表达式的使用无效。
//g++7.2.0失败,原因是:没有用于调用的匹配函数
//‘C1::C1(bool)’。
//修复方法是使用mem初始值设定项id加括号的init list,如下所示:
//:基类{args…}。。。
}
};
int main(){
A(真,1.0F);
标准::printf(“%d%f%d%f%d%f\n”,a.a,a.b,a.c,a.d,a.e,a.f);
}
我的问题是:在C++14标准中,哪里特别提到mem初始值设定项列表中的参数包扩展只能与mem初始值设定项的第二个替代项一起工作?或者,使用第一种方法是否可以,但我需要一些语法技巧来避免歧义?gcc bug,@liliscent:我将与gcc维护人员一起检查这一点。谢谢。@lilistence我在@lilistence提交了问题,我在GCC bugzilla中提交了错误
#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);
}