Почему GCC пересылает аргументы этого векторного конструктора конструктору содержащегося типа, а Clang — нет?

Рассмотрим следующий тип манекена:

struct Foo{
Foo(int x) : x{x}{}

template<std::ranges::range R>
Foo(R r) : x{std::accumulate(r.begin(), r.end(), 0, [](int x, const auto& foo){return x + foo.x;})}{}

int x;
};

Если я теперь инициализирую std::vector<Foo> другим std::vector<Foo>, результат будет отличаться в зависимости от компилятора.

std::vector<Foo> foos{Foo{1}, Foo{2}, Foo{3}};
std::vector<Foo> foos_copy{foos};

В clang foos == foos_copy GCC пересылает вектор конструктору Foo на основе диапазона, в результате чего foos_copy содержит только один элемент, как если бы он был

std::vector<Foo> foos_copy{{foos}};

Полный пример см. здесь: https://godbolt.org/z/G1dhbKsoc

Мне просто интересно, почему существует эта разница и какой компилятор правильный.

Это отличный полный вопрос, я не понимаю, почему за него проголосовали.

François Andrieux 03.06.2024 21:13

Кстати. «как будто это было std::vector<Foo> foos_copy{{foos}};» неверно. Как будто вместо этого был std::vector<Foo> foos_copy({foos});.

user17732522 03.06.2024 21:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
2
84
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

CWG2137 изменил правила инициализации списка типа класса из его собственного типа. Раньше конструктор копирования/перемещения имел приоритет. Теперь конструктор std::initializer_list имеет приоритет, но если жизнеспособного конструктора не существует, он все равно возвращается к конструктору копирования/перемещения (или другому конструктору, который может принимать тот же тип).

Этот вопрос любопытен, поскольку резолюция была принята в 2016 году, но Ричард Смит, отправитель проблемы и основной участник Clang, фактически не реализовал резолюцию в Clang. Я спросил Ричарда, не потому ли это, что он попробовал реализовать это и обнаружил, что это нарушило слишком много кода, но он не ответил. Я вижу, что недавно была предпринята попытка реализовать это в Clang, но она была отменена через 5 дней после слияния, что может быть недостаточно для того, чтобы внешние пользователи сообщили о регрессиях.

В любом случае, стандарт гласит, что foos_copy должен содержать только 1 элемент, и в зависимости от того, как вы на это смотрите, либо Clang еще не реализовал его, либо само разрешение неправильное, и в конечном итоге его придется отменить. (Обратите внимание, что в отличие от того, что сказал пользователь 17732522 в комментариях, CWG2742 не выступает за отмену CWG2137. Вместо этого автор предложенной резолюции CWG2742 случайно написал формулировку, которая возвращает CWG2137.)

Другие вопросы по теме

Похожие вопросы

Что определяет, будет ли двоичный файл, скомпилированный с помощью MinGW, иметь доступ к API Win32 или API POSIX?
Загрузка артефакта символов, созданного PublishSymbols@2, из графического интерфейса Azure DevOps невозможна
Почему Boost уделяет особое внимание потокобезопасности для отдельных объектов?
Ошибка установки Хоровода в Docker — PIP — C++17
Можно ли статически собрать opencv под Linux, не имея проблем с отсутствующими/несовместимыми библиотеками?
Виртуальный жесткий диск — ata pio и сохранение состояния жесткого диска, операции записи в одном и том же месте
Как объявить конструктор с аргументами ровно nRow*nCol типа T?
C++, как выполнить структурированную привязку к существующим переменным?
FormatMessage возвращает символ char*, содержащий нули между каждым символом... почему?
Может ли разыменование указателя p в том же выражении, в котором он увеличивается, привести к неопределенному поведению?