是否允许std :: tuple的实现失败并触发空类元素的派生到基础转换?

Joh*_*itb 18 c++ language-lawyer c++11 stdtuple

此代码不能使用GCC4.7进行编译

struct A {};
void f(A);

struct B { B(std::tuple<A>); };
void f(B);

int main() {
  f(std::make_tuple(A()));
}
Run Code Online (Sandbox Code Playgroud)

因为GCC派生自A利用空基类优化.然而,这导致海湾合作委员会挑选f(A)和抱怨

错误:'A'是一个无法访问的基础'tuple<A>'

这个错误是由C++标准授予的,还是仅仅是libstdc ++的错误?

eca*_*mur 2

根据第 17 条图书馆介绍

17.5.2.3 私有成员[objects.within.classes]

1 - 第 18 条至第 30 条和附录 D 未指定类别的表示,并有意省略类别成员的说明。根据需要实现第 18 条到第 30 条和附录 D 中指定的成员函数的语义,实现可以定义静态或非静态类成员,或两者。

1.4 实施合规性 [intro.compliance]支持这一点:

3 - 对于类和类模板,库子句指定部分定义。未指定私有成员(第 11 条),但每个实现应根据库条款中的描述提供它们以完成定义。

通过继承实现指定的语义没有在第 17 条中明确讨论,但通过上面 17.5.2.3 的第 3 段隐式允许:

3 - 实现可以使用提供等效外部行为的任何技术。

例如,这就是基于节点的有序关联容器如何通过继承共享实现细节(最终包括类成员)。

由于 的外部行为tuple在作为类成员和直接继承它之间发生了变化A,并且由于这种行为的变化会导致拒绝其他格式良好的程序(而不是仅仅更改类的sizeof),因此 libstdc++ 违反了标准。