此代码不能使用GCC4.7编译
struct A {};
void f(A);
struct B { B(std::tuple<A>); };
void f(B);
int main() {
f(std::make_tuple(A()));
}
因为GCC是从A
派生出来的,利用了空基类的优化。然而,这导致GCC选择了f(A)
并抱怨
错误:
'A'
是不可访问的'tuple<A>'
基目录
这个错误是C++标准允许的,还是仅仅是libstdc++的一个错误?
发布于 2012-12-17 18:45:09
根据第17条库简介
17.5.2.3私有成员objects.within.classes
1-第18至30条和附件D没有规定类别的表示,并故意省略了类别成员的说明。实现可以根据需要定义静态和/或非静态类成员,以实现第18至30条和附件D中指定的成员函数的语义。
1.4 Implementation compliance intro.compliance支持此功能
3-对于类和类模板,library子句指定部分定义。没有指定私有成员(第11条),但每个实现都应提供它们,以根据库子句中的描述完成定义。
通过继承实现指定的语义在第17条中没有明确讨论,但通过上面17.5.2.3的第3段隐含地允许:
3-实现可以使用任何提供等效外部行为的技术。
例如,这就是基于节点的有序关联容器如何通过继承共享实现细节(最终包括类成员)的方式。
由于tuple
的外部行为在将A
作为类成员和直接继承它之间进行了更改,并且由于这种行为更改会导致拒绝其他格式良好的程序(而不仅仅是更改类的sizeof
),因此libstdc++违反了标准。
发布于 2012-12-17 00:07:05
我会说no。
至少:
§20.4.1 tuple.general
1/ ...具有两个参数的元组的实例化类似于具有相同的两个参数的对的实例化。请参见20.3。
然而:
#include <tuple>
struct A {};
void f(A);
struct B { B(std::tuple<A, A>); };
void f(B);
int main() {
f(std::make_tuple(A(), A()));
}
fails具有以下特性:
Compilation finished with errors:
source.cpp: In function 'int main()':
source.cpp:10:30: error: 'A' is an ambiguous base of 'std::tuple<A, A>'
source.cpp:4:6: error: initializing argument 1 of 'void f(A)'
我非常怀疑这是“旗帜报”的意图。
尽管如此,至少可以说20.4节是相当简洁的……
https://stackoverflow.com/questions/13902910
复制相似问题