Разрешена ли реализация std :: tuple с ошибкой запуска преобразования производного в базовое значение для пустых элементов класса?

Этот код не компилируется с 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 ++?

18

Решение

Под пунктом 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 ++ является нарушением стандарта.

2

Другие решения

я бы сказал нет.

По крайней мере:

§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 довольно лаконичен …

3

По вопросам рекламы [email protected]