Подтвердить что ты не робот

Реализована ли реализация 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>'

Является ли эта ошибка предоставленной стандартом С++ или это просто ошибка libstdС++?

4b9b3361

Ответ 1

В разделе 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 - Реализация может использовать любую технику, которая обеспечивает эквивалентное внешнее поведение.

Так, например, упорядоченные ассоциативные контейнеры node могут совместно использовать детали реализации (включая, в конечном счете, членов класса) через наследование.

Поскольку внешнее поведение tuple изменяется между тем, что A является членом класса и непосредственно наследует его, а так как это изменение поведения вызывает отказ от хорошо сформированных программ (в отличие от простое изменение sizeof класса), libstdС++ нарушает Стандарт.

Ответ 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 является довольно кратким...