Этот код не компилируется с 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 ++?
Под пунктом 17 Введение в библиотеку:
17.5.2.3 Частные члены [objects.within.classes]
1 — Пункты с 18 по 30 и Приложение D не определяют представление классов и намеренно опускают спецификацию членов класса. Реализация может определять статические или нестатические члены класса, или и то, и другое, как необходимо для реализации семантики функций-членов, указанных в разделах 18–30 и Приложении D.
Это поддерживается 1.4 Соответствие реализации [intro.compliance]:
3 — Для классов и шаблонов классов разделы библиотеки задают частичные определения. Частные члены (пункт 11) не указываются, но каждая реализация должна предоставлять их для завершения определений в соответствии с описанием в пунктах библиотеки.
Реализация указанной семантики посредством наследования явно не обсуждается нигде в разделе 17, но это неявно разрешено в пункте 3 17.5.2.3 выше:
3 — Реализация может использовать любую технику, которая обеспечивает эквивалентное внешнее поведение.
Вот как, например, упорядоченные ассоциативные контейнеры на основе узлов могут совместно использовать детали реализации (включая, в конечном счете, членов класса) посредством наследования.
Поскольку внешнее поведение tuple
меняется между A
как член класса и непосредственно наследует его, и так как это изменение поведения вызывает отказ от других хорошо сформированных программ (в отличие от простого изменения sizeof
класса), libstdc ++ является нарушением стандарта.
я бы сказал нет.
По крайней мере:
§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()));
}
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 довольно лаконичен …