Вопрос про лямбды
От: LaptevVV Россия  
Дата: 10.09.24 08:52
Оценка: :))
Есть два исходных файла 1.срр и 2.срр
В обоих определена одна и та же лямбда на глобальном уровне
auto next_operands = [](random_t &gen, distribution_t uid){
    operands_t operand;
    operand.left = uid(gen); operand.right = uid(gen);
    return operand;
};

Понятно, что компиляция файлов проходит без ошибок

Но почему все собирается без ошибок?
У лямбд внутреннее связывание, как у констант ?
Или это связано с выводом типов и у них таки разный тип получается ?
Где про это прочитать ?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Вопрос про лямбды - нашел ответ на StackOverflow на русском
От: LaptevVV Россия  
Дата: 10.09.24 09:03
Оценка: +3
Тип объекта замыкания (closure object), порождаемого лямбда-выражением, никак не зависит от параметров лямбды и не определяется ими.
Наличие или отсутствие аргументов по умолчанию здесь никакой роли не играет.
Каждое лямбда-выражение порождает новый уникальный тип — это все, что вам нужно знать о типе объекта замыкания.
Даже если два лямбда-выражения полностью идентичны, они все равно получат никак не связанные друг с другом уникальные типы.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Вопрос про лямбды
От: Великий Реверс google
Дата: 10.09.24 09:03
Оценка:
две одинаковые по типу лямбды
имею разный мангл
хз вроде бы это где то описано в стандарте
типа каждая лямбда уникальна
Re: Вопрос про лямбды
От: vopl Россия  
Дата: 10.09.24 09:06
Оценка: 1 (1)
Здравствуйте, LaptevVV, Вы писали:

LVV>Есть два исходных файла 1.срр и 2.срр

LVV>В обоих определена одна и та же лямбда на глобальном уровне
LVV>
LVV>auto next_operands = [](random_t &gen, distribution_t uid){
LVV>    operands_t operand;
LVV>    operand.left = uid(gen); operand.right = uid(gen);
LVV>    return operand;
LVV>};
LVV>

LVV>Понятно, что компиляция файлов проходит без ошибок

LVV>Но почему все собирается без ошибок?

LVV>У лямбд внутреннее связывание, как у констант ?
LVV>Или это связано с выводом типов и у них таки разный тип получается ?
LVV>Где про это прочитать ?

https://en.cppreference.com/w/cpp/language/lambda

The lambda expression is a prvalue expression of unique unnamed non-union non-aggregate class type...


То есть, каждая лямбда по определнию уникальна, и уже на этом основании не составит коллизии ни с какой другой лямбдой, даже если они рядышком и полностью одинаковые будут. Ну и в нагрузку, она еще и безымянна, то есть, на уровень линковки вообще не выходит, следовательно, никаких конфликтов там быть не может из за "одинаковых лямбд".
Re[2]: Вопрос про лямбды
От: andrey.desman  
Дата: 10.09.24 09:51
Оценка: +1
Здравствуйте, vopl, Вы писали:

V>То есть, каждая лямбда по определнию уникальна, и уже на этом основании не составит коллизии ни с какой другой лямбдой, даже если они рядышком и полностью одинаковые будут. Ну и в нагрузку, она еще и безымянна, то есть, на уровень линковки вообще не выходит, следовательно, никаких конфликтов там быть не может из за "одинаковых лямбд".


Здесь дело не в лямбдах, а в глобальных переменных next_operands. За счет разных типов коллизии нет.
Re[3]: Вопрос про лямбды
От: vopl Россия  
Дата: 10.09.24 10:05
Оценка:
Здравствуйте, andrey.desman, Вы писали:

AD>Здравствуйте, vopl, Вы писали:


V>>То есть, каждая лямбда по определнию уникальна, и уже на этом основании не составит коллизии ни с какой другой лямбдой, даже если они рядышком и полностью одинаковые будут. Ну и в нагрузку, она еще и безымянна, то есть, на уровень линковки вообще не выходит, следовательно, никаких конфликтов там быть не может из за "одинаковых лямбд".


AD>Здесь дело не в лямбдах, а в глобальных переменных next_operands. За счет разных типов коллизии нет.


Ну, давай попробуем эту мысль подумать. Если в приведенном ТС куске кода next_operands это глобальная переменная, объявляемая в двух единицах трансляции — то линкер безусловно будет ругаться на нее. То есть, это не ситуация ТС... Или это именно та ситуация? Тогда ТС что то упустил, так как в этом случае ошибка линкера таки будет иметь место.

Я так понял, что у него next_operands не является глобальной переменной. ТС вообще говорит о лямбде а не о next_operands.
Re: Вопрос про лямбды
От: σ  
Дата: 10.09.24 10:25
Оценка: +2
LVV>Есть два исходных файла 1.срр и 2.срр
LVV>В обоих определена одна и та же лямбда на глобальном уровне

LVV>все собирается без ошибок

/usr/bin/ld: /tmp/cc5qfXUR.o:(.bss+0x0): multiple definition of `next_operands'; /tmp/ccAK4JPQ.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
https://wandbox.org/permlink/1O6EcKxBDOiWs61B
Отредактировано 10.09.2024 10:28 σ . Предыдущая версия . Еще …
Отредактировано 10.09.2024 10:25 σ . Предыдущая версия .
Re[4]: Вопрос про лямбды
От: andrey.desman  
Дата: 10.09.24 10:57
Оценка:
Здравствуйте, vopl, Вы писали:

AD>>Здесь дело не в лямбдах, а в глобальных переменных next_operands. За счет разных типов коллизии нет.

V>Ну, давай попробуем эту мысль подумать. Если в приведенном ТС куске кода next_operands это глобальная переменная, объявляемая в двух единицах трансляции — то линкер безусловно будет ругаться на нее. То есть, это не ситуация ТС... Или это именно та ситуация? Тогда ТС что то упустил, так как в этом случае ошибка линкера таки будет иметь место.

А, ну да, глобалы не манглятся... Судя по всему, у него какой-то странный компилятор или код не весь.

V>Я так понял, что у него next_operands не является глобальной переменной. ТС вообще говорит о лямбде а не о next_operands.


Так о самой лямбде смысла нет говорить, с ней и так все понятно.
Re[2]: Вопрос про лямбды
От: LaptevVV Россия  
Дата: 10.09.24 11:22
Оценка:
LVV>>Есть два исходных файла 1.срр и 2.срр
LVV>>В обоих определена одна и та же лямбда на глобальном уровне

LVV>>все собирается без ошибок

σ>
/usr/bin/ld: /tmp/cc5qfXUR.o:(.bss+0x0): multiple definition of `next_operands'; /tmp/ccAK4JPQ.o:(.bss+0x0): first defined here
σ>collect2: error: ld returned 1 exit status
https://wandbox.org/permlink/1O6EcKxBDOiWs61B

Спасибо.
Проверю в Линуксе.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Вопрос про лямбды - как интересно!
От: LaptevVV Россия  
Дата: 10.09.24 11:53
Оценка:
Один и тот же проект.
Под виндой c mingw — ошибок не выдает.
А в линуксе g++ 10.1 — выдает ошибку линкера
pedantic стоит и там, и там.
-Wall стоит и там, и там.

Нетрудно переименовать, чтобы в каждом файле было разное имя.

Но почему разное поведение компилятора ?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Вопрос про лямбды - как интересно!
От: vopl Россия  
Дата: 10.09.24 12:21
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Один и тот же проект.

LVV>Под виндой c mingw — ошибок не выдает.

vopl@vopl MINGW64 ~/tmp $ cat a.cpp
auto g = []{};
int main(){}

vopl@vopl MINGW64 ~/tmp $ cat b.cpp
auto g = []{};

vopl@vopl MINGW64 ~/tmp $ g++ a.cpp b.cpp
D:/c/opt/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: D:\c\opt\msys64\tmp\ccwWYFsV.o:b.cpp:(.bss+0x0): multiple definition of `g'; D:\c\opt\msys64\tmp\ccQ3Iiqi.o:a.cpp:(.bss+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
Re[2]: Вопрос про лямбды - как интересно!
От: andrey.desman  
Дата: 10.09.24 12:37
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Нетрудно переименовать, чтобы в каждом файле было разное имя.


Может статик или анонимное пространство имен? Зачем он экстерн?
Re[3]: Вопрос про лямбды - как интересно!
От: LaptevVV Россия  
Дата: 10.09.24 12:41
Оценка:
LVV>>Нетрудно переименовать, чтобы в каждом файле было разное имя.
AD>Может статик или анонимное пространство имен? Зачем он экстерн?
Нет, не статик.
Но анонимное пространство имен — да.
Но код совершенно одинаковый и в винде, и в линуксе.
Я ж и сам удивился, что у меня все собирается без проблем.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: Вопрос про лямбды - как интересно!
От: andrey.desman  
Дата: 10.09.24 12:43
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>>>Нетрудно переименовать, чтобы в каждом файле было разное имя.

AD>>Может статик или анонимное пространство имен? Зачем он экстерн?
LVV>Нет, не статик.
LVV>Но анонимное пространство имен — да.

Не понял, оно сейчас в анонимном?
Re[2]: Вопрос про лямбды - как интересно!
От: σ  
Дата: 10.09.24 12:52
Оценка: +1
LVV>Но почему разное поведение компилятора ?
Потому что стандарт разрешает вести себя как угодно
Re[5]: Вопрос про лямбды - как интересно!
От: LaptevVV Россия  
Дата: 10.09.24 12:59
Оценка:
LVV>>>>Нетрудно переименовать, чтобы в каждом файле было разное имя.
AD>>>Может статик или анонимное пространство имен? Зачем он экстерн?
LVV>>Нет, не статик.
LVV>>Но анонимное пространство имен — да.
AD>Не понял, оно сейчас в анонимном?

Да, все имена объявлены старым дедовским способом.
Просто как глобальные переменные.

Обычные переменные, естественно, с одинаковыми именами
не позволяет в двух разных файлах объявить.
Даже разных типов.

А вот с лямбдами такая получилась засада.
Абсолютно две одинаковые лямбды с одинаковыми именами, объявленные глобально,
mingw кушает, а в линуксе выдает нормально ошибку линкера.
Причем еще и пишет, в каком файле была определена первый раз.
Что и должно быть.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[6]: Вопрос про лямбды - как интересно!
От: vopl Россия  
Дата: 10.09.24 13:09
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>А вот с лямбдами такая получилась засада.

LVV>Абсолютно две одинаковые лямбды с одинаковыми именами, объявленные глобально,
LVV>mingw кушает, а в линуксе выдает нормально ошибку линкера.

Можете привести полный код, который под mingw не приводит к ошибке пожалуйста? Весьма интересно как это так
Re[3]: Вопрос про лямбды - как интересно!
От: LaptevVV Россия  
Дата: 10.09.24 13:13
Оценка:
LVV>>Но почему разное поведение компилятора ?
σ>Потому что стандарт разрешает вести себя как угодно
Это я не совсем понял.
unspecified ?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: Вопрос про лямбды - как интересно!
От: σ  
Дата: 10.09.24 13:15
Оценка: 15 (1)
LVV>>>Но почему разное поведение компилятора ?
σ>>Потому что стандарт разрешает вести себя как угодно
LVV>Это я не совсем понял.
LVV>unspecified ?
IFNDR
Re: Вопрос про лямбды
От: B0FEE664  
Дата: 10.09.24 13:52
Оценка: +1
Здравствуйте, LaptevVV, Вы писали:

  Скрытый текст
LVV>Есть два исходных файла 1.срр и 2.срр
LVV>В обоих определена одна и та же лямбда на глобальном уровне
LVV>
LVV>auto next_operands = [](random_t &gen, distribution_t uid){
LVV>    operands_t operand;
LVV>    operand.left = uid(gen); operand.right = uid(gen);
LVV>    return operand;
LVV>};
LVV>

LVV>Понятно, что компиляция файлов проходит без ошибок


LVV>Но почему все собирается без ошибок?

Так в стандарте.

LVV>У лямбд внутреннее связывание, как у констант ?

Нет, но их можно объявить константами.

LVV>Или это связано с выводом типов и у них таки разный тип получается ?

Тип разный, но это не столь важно.

LVV>Где про это прочитать ?

Нарушение ODR, полагаю. Wiki

Вообще говоря это, наверное, худший из подводных камней C++. В больших проектах невозможно отследить отсутствие пересечений по именам.
И каждый день — без права на ошибку...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.