LINUX.ORG.RU

Модули... модули? Какие модули?!

 ,


0

5

Привет, ЛОР!

Решил я тут взять C++ для одного своего маленького проекта. Давно ничего сложнее багфиксов в старый код не писал на этом языке по причине его особой не нужности, но тут подумал: «Почему бы и нет?» Естественно, хочу C++ со всеми последними вкусностями, в частности нормальными модулями.

Скажи, ЛОР, как эти модули вообще использовать? Если в рамках моего проекта всё примерно понятно, то использование модулей из сторонних библиотек вызывает много вопросов. Стандартная библиотека, как я понимаю, в модули до сих пор не обёрнута?

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

import <iostream>;
import <string>;

std::string s = "Hello World";

int main(void)
{
  std::cout << s << std::endl;
}
$ g++ -std=c++2b -fmodules-ts mod.cc -o mod
In module imported at mod.cc:1:1:
/nix/store/z9jxhrbxm5lxrjpia9xcqjgk990ffr2j-gcc-11.1.0/include/c++/11.1.0/iostream: error: failed to read compiled module: No such file or directory
/nix/store/z9jxhrbxm5lxrjpia9xcqjgk990ffr2j-gcc-11.1.0/include/c++/11.1.0/iostream: note: compiled module file is ‘gcm.cache/./nix/store/z9jxhrbxm5lxrjpia9xcqjgk990ffr2j-gcc-11.1.0/include/c++/11.1.0/iostream.gcm’
/nix/store/z9jxhrbxm5lxrjpia9xcqjgk990ffr2j-gcc-11.1.0/include/c++/11.1.0/iostream: note: imports must be built before being imported
/nix/store/z9jxhrbxm5lxrjpia9xcqjgk990ffr2j-gcc-11.1.0/include/c++/11.1.0/iostream: fatal error: returning to the gate for a mechanical issue
compilation terminated.
$ 
$ clang++ -std=c++2b -fmodules-ts mod.cc -o mod
mod.cc:1:8: error: header file <iostream> (aka '/nix/store/dlni53myj53kx20pi4yhm7p68lw17b07-gcc-10.3.0/include/c++/10.3.0/iostream') cannot be imported because it is not known to be a header unit
import <iostream>;
       ^
mod.cc:2:8: error: header file <string> (aka '/nix/store/dlni53myj53kx20pi4yhm7p68lw17b07-gcc-10.3.0/include/c++/10.3.0/string') cannot be imported because it is not known to be a header unit
import <string>;
       ^
mod.cc:4:1: error: use of undeclared identifier 'std'
std::string s = "Hello World";
^
mod.cc:8:3: error: use of undeclared identifier 'std'
  std::cout << s << std::endl;
  ^
mod.cc:8:21: error: use of undeclared identifier 'std'
  std::cout << s << std::endl;
                    ^
5 errors generated.

GCC и Clang почти последние: 11.1 и 12.0.1. Выходит, модули не работают? Что делать, ЛОР? Отложить C++ до лучших времён?

★★★★★

Последнее исправление: hateyoufeel (всего исправлений: 2)

Я бы предложил, как и все нормальные люди, не гнаться за новинками а использовать 11 или 14 стандарты.

NAY_GIGGER
()
Ответ на: комментарий от NAY_GIGGER

Я бы предложил, как и все нормальные люди, не гнаться за новинками а использовать 11 или 14 стандарты.

Почему? Ждать 10 лет после выхода стандарта – это как-то очень странно.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

Лично мне очень нравятся старые плюсы. Я всегда был, есть и буду за платформо-специфичный код, т.к. это частично гарантия что он будет работать. Да, это трата времени но это и опыт и знания о возможных подводных камнях.

NAY_GIGGER
()
Ответ на: комментарий от filosofia

Модули пока работают через жопу

Локально они работают вполне неплохо. У меня вот сейчас в проекте ни одного хидера нет. Вопрос именно про внешние библиотеки, в том числе стандартную.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от NAY_GIGGER

Да, это трата времени но это и опыт и знания о возможных подводных камнях.

Это знания и опыт в подводных камнях довольно убогого язычка. 20 лет назад, возможно, это было оправданно ввиду отсутствия альтернатив. Сейчас это далеко не так.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

Локально они работают вполне неплохо. У меня вот сейчас в проекте ни одного хидера нет.

А зачем тебе локально в проекте модули? Можешь убедить меня, почему мне это нужно? Я пока вообще не вижу смысла клепать модуль чаще, чем один на проект. Хидеры много больше возможностей дают, внутри проекта это много удобней.

kvpfs ★★
()
Ответ на: комментарий от hateyoufeel

В этом и есть черезжопие. Тулинг не готов. Есть какие-то локальные прогрессы, но в среднем по больнице пока тухло.

Я не до конца понимаю твой кейз. Ты хочешь новые плюсы только ради модулей, раз ты говоришь «если модули не готовы, отложу до лучших времён»?

filosofia
()
Ответ на: комментарий от NAY_GIGGER

Я бы предложил, как и все нормальные люди, не гнаться за новинками а использовать 11 или 14 стандарты.

C++17 почему не упомянул?

rumgot ★★★★★
()
Ответ на: комментарий от peregrine

Ну к слову сказать C++17 уже можно использовать в своих проектах, хотя на энтерпрайз ему рановато.

Всегда интересно слышать аргументы таких заявлений. Интересно, сможешь ли ты выдать что-то более конкретное чем «надо подождать, подумать».

ЗЫ у меня вполне пишут новый код на С++20 в систему, обслуживающую десятки миллиардов денег.

filosofia
()
Ответ на: комментарий от rumgot

Когда легаси перепишут на него и все используемые на проде компиляторы подтянут все фичи. А то есть ещё и легаси прода, где может не использоваться свежий clang и gcc как и свежая студия с её компилятором. А то что есть отдельный вид проды куда можно велосипеды свежие и сырые совать это значит что там легаси мало и организация не слишком большая. Из большой проды в США ещё фортран не выпилили.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

Это пустословие, сорян. Фортран используют внезапно из-за фортрана, а не версии компилятора. Вообще забавно слышать два слова «прод» и «компилятор» рядом. Интерпрайз такой интерпрайз.

filosofia
()

В Visual Studio твой пример работает: https://imgur.com/a/SRhX2ex

(хотя не всё с модулями работает, в багтрекере можно поискать баги связанные с модулями, вот как пример: https://developercommunity.visualstudio.com/t/Modules-and-chrono_literals/1511719 )

А так, clang у себя на сайте пишет что они не поддерживают модули:

https://clang.llvm.org/cxx_status.html#cxx20

В gcc попробуй так(лень включать VirtualBox, но по идее должно заработать):

$ g++ -std=c++20 -fmodules-ts -x c++-header /usr/include/c++/11/iostream

$ g++ -std=c++20 -fmodules-ts -x c++-header /usr/include/c++/11/string

$ g++ -std=c++20 -fmodules-ts mod.cc -o mod
fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 3)
Ответ на: комментарий от kvpfs

А зачем тебе локально в проекте модули? Можешь убедить меня, почему мне это нужно?

Можешь убедить меня, что мне нужно тратить время на убеждение тебя в чём-то?

hateyoufeel ★★★★★
() автор топика

Имхо, модули на данный момент стоит рассматривать как более продвинутую альтернативу PCH

Если в рамках моего проекта всё примерно понятно

… то и прекрасно

annulen ★★★★★
()
Ответ на: комментарий от fsb4000

Забавно, потому что у меня clang вполне собирает проект с модулями внутри проекта.

За ссылку на статус реализации спасибо, кстати.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

Забавно, потому что у меня clang вполне собирает проект с модулями внутри проекта.

Clang dev:

On the Clang side we've had non-standard modules for a while, but need to implement the rest of the C++20 rules. There's not a high sense of urgency here from the large contributors since they already get the compile time benefits using the existing system.

https://www.reddit.com/r/cpp/comments/ok8o4t/why_is_there_still_such_poor_compiler_support_for/h56jhwt?utm_source=share&utm_medium=web2x&context=3

Если есть время можешь почитать всю ветку: https://www.reddit.com/r/cpp/comments/ok8o4t/why_is_there_still_such_poor_compiler_support_for/

fsb4000 ★★★★★
()
Ответ на: комментарий от hateyoufeel

Ясно, так я примерно и думал, очередной пустой тред ради позлить тупых плюсовиков. Ты даже сам не понимаешь зачем тебе модули нужны, нахватался модных словечек и повторяешь.

С хидерами имея один конфиг файл (пусть это будет мэп сочетний клавиш на функции), можно, например, сгенерить несколько сущностей без всякого дубляжа - map с key_mapping + справку по командам + ещё что угодно. Ты же предложишь какую-нибудь модную супер-пупер рефлексию и лишние телодвижения в рантайме.

kvpfs ★★
()
Ответ на: комментарий от rumgot

Потому что я только файловую систему оттуда использовал. Синтаксис все так же от 11/14.

NAY_GIGGER
()
Ответ на: комментарий от kvpfs

Я ничего тебе не буду предлагать. Но мне нравится твоё внимание к моей персоне :DDDD

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от fsb4000

Ага, спасибо. Удивительно, что всем вот настолько пофиг. Скоро 2021 кончится, а поддержки 20 стандарта до сих пор полностью нет. Такое чувство, что комитет и писатели компиляторов вообще друг с другом не разговаривают.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Гуйня с Qt. У Rust и Haskell есть биндинги к QML, но я подумал, что для несложного проекта вполне можно на плюсах нативно написать.

hateyoufeel ★★★★★
() автор топика

c++ для нового проекта имеет смысл выбирать только чтобы поржать над c++

anonymous
()
Ответ на: комментарий от kvpfs

С хидерами имея один конфиг файл (пусть это будет мэп сочетний клавиш на функции), можно, например, сгенерить несколько сущностей без всякого дубляжа - map с key_mapping + справку по командам + ещё что угодно

с модулями, инклуды никто не отменял, и препроцессор - тоже. инклудь и препроцессируй в свое удовольствие прямо внутри модуля

alysnix ★★★
()
Ответ на: комментарий от anonymous

А он разве умер? Я слышал, кто-то ещё пилит и не может остановиться.

Но нет. Мне просто нужен небольшой гуй для одного сервиса. Работы на неделю, может.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от alysnix

Это только адекватные понимают, что хидеры не отменяются, модули их не заменят. Самые модные убеждены в том, что слово include нужно вырезать со всей кодовой базы и больше никогда не использовать. Да и от этого веет жгучим желанием избавиться от этого гнилого легаси:

У меня вот сейчас в проекте ни одного хидера нет

СТД на модулях - ок, обертка проекта в модлуь - ок, но юзать модули внутри проекта - смысла пока не вижу.

kvpfs ★★
()
Последнее исправление: kvpfs (всего исправлений: 1)

@hobbit за каким-то хреном трёт безобидные комментарии. Ну да ладно.

@kvpfs:

Это у тебя какая-то истерика после безобидного вопроса «А зачем тебе локально в проекте модули?». Я вот не понимаю зачем (я не про модульную стд), думал твой выбор осознанный, можешь сказать - будет вот такой-то профит, я бы может тоже захотел. Но твой выбор не базируется на практическом опыте.

Как минимум, отсутствие дурацкого разделения кода, когда типы и объявления функций в одних файлах, а реализация – в других. Мне это сильно упрощает жизнь и спасает от безумия. Можно даже не париться и писать реализацию методов класса прямо внутри объявления этого класса, не опасаясь что всё это будет скопировано 10 раз. Не надо думать, пихать шаблонные функции куда-то отдельно или нет.

Заголовочные файлы – это какое-то нелепое наследие из 70х, которое непонятным образом сохранилось до наших дней. Даже в Паскале их уже не было.

Очень приятный пример модулей: сделать prelude для проекта. На заголовках такого не сделать нормально, потому что из заголовков экспортируется вообще всё. Модули в C++ позволяют определить, что именно я хочу переэкспортировать наружу.

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от Pavval

Время компиляции

В этом деле модули успешно сольют хидерам, ибо много разумней параллелить сборку безмодульной хидерной модели (напоминаю, что я не отрицал нужность модуля-обертки над целым проектом или стд).

kvpfs ★★
()
Ответ на: комментарий от hateyoufeel

На заголовках такого не сделать нормально, потому что из заголовков экспортируется вообще всё. Модули в C++ позволяют определить, что именно я хочу переэкспортировать наружу.

нету никаких «заголовков». это лишь текстовые куски, которые препроцессор вставит там, где будет директива #include.

отсюда вывод - в «заголовках» пишется только то, что вы хотите показать наружу и вставить во внешний файл. и инклудить в сами заголовки надо только то, что необходимо для компиляции ЭТОГО заголовка.

в человечных модульных языках для этого есть definition module - где перечисляются экспортируемые обьекты, и implementaion module - где экспортируемые обьекты и все внутренности реализуются.

компилятор читает только оттранслированные definition модули, при импорте.

а когда все в одном модуле с пометкой export… а сам модуль размером с черти сколько строк… то понять, что из него экспортруют - сложно. а сокращение списка экспорта, это считай нужный рефакторинг.

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

реальная проблема хидеров в том, что они могут быть вообще не компилируемые сами по себе, и давать побочные эффекты, типа если в хидере фигурную скобочку открыть…и не закрыть.

а вот все модули должны быть компилируемы и таких эффектов там не будет.

alysnix ★★★
()
Ответ на: комментарий от hateyoufeel

@hobbit за каким-то хреном трёт безобидные комментарии. Ну да ладно.

Самое забавное, что как программист я как раз за внедрение модулей. А как модератор — категорически против перевода технических дискуссий в плоскость «у собеседника подгорела жопа, значит я всё правильно написал».

Как минимум, отсутствие дурацкого разделения кода, когда типы и объявления функций в одних файлах, а реализация – в других. Мне это сильно упрощает жизнь и спасает от безумия.

Это, кстати, к модульности имеет довольно косвенное отношение. На мой взгляд, отделение объявления класса от реализации делает код более читаемым. Это необязательно отдельные файлы. Как в том же паскале (секции interface и implementation) — тоже вполне разумный подход.

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

На мой взгляд, отделение объявления класса от реализации делает код более читаемым.

Это потому что тебе документацию лень писать, да? :)

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

документацию лень писать

Поэтому литературное/грамотное программирование, как Кнут завещал.

anonymous
()
Ответ на: комментарий от alysnix

в человечных модульных языках для этого есть definition module - где перечисляются экспортируемые обьекты, и implementaion module - где экспортируемые обьекты и все внутренности реализуются.

Это в каких? Потому что я кроме как Паскаль с потомками вспомнить не могу тут.

а когда все в одном модуле с пометкой export… а сам модуль размером с черти сколько строк… то понять, что из него экспортруют - сложно. а сокращение списка экспорта, это считай нужный рефакторинг.

Тут можно предложить не писать модули на 100000 строк, но проблема есть. Мне нравятся export lists в Haskell в заголовках модулей.

а форвард декларация класса все равно нужна, поскольку неизбежна будет циклическая зависимость классов в релизации

Почему неизбежно? Я её в 90% случаев успешно избегаю. И это другая проблема C++, потому что кто-то до сих пор не может забыть про однопроходные компиляторы из 70х.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

В части такой документации желательно, чтобы код документировал сам себя. Если код невозможно читать без руководства программиста, то по закону Мэрфи через какое-то время они обязательно разойдутся, и поддерживающий код программист будет решать увлекательный квест: где ошибка?

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

Да нет, вполне можно системой автогенерации доков помечать, какие функции являются частью API. Это не проблема, на самом деле.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

Ну и раз пошла такая пьянка:

Локально они работают вполне неплохо. У меня вот сейчас в проекте ни одного хидера нет. Вопрос именно про внешние библиотеки, в том числе стандартную.

На мой взгляд, это уже хорошо. Внешние библиотеки обычно не перекомпилируются на каждый чих. А стандартную библиотеку дёргать через модули будет разумно тогда, когда станет общепринятой практикой (т.е. не скоро).

Я модулями интересуюсь в первую очередь именно в разрезе «локальной» работы.

hobbit ★★★★★
()
Ответ на: комментарий от hateyoufeel

Это в каких? Потому что я кроме как Паскаль с потомками вспомнить не могу тут.

modula-2, modula-3 … как минимум.

экспорт прям в модуле реализации ввели чисто ради попсовости и меньшей писанины. и грубо ошиблись.

есть другой ход. можно делать экспорт прямо в единственном модуле, но тогда по дефиниции языка компилятор обязан автоматически генерить текстовый файл экспортов из модуля. и именно он используется при импорте. то есть заменить писанину ручками, автоматической генерацией. тогда по этому файлу можно понять - что там наэкспортировали шаловливые ручонки погромиста.

alysnix ★★★
()
Ответ на: комментарий от hobbit

На мой взгляд, отделение объявления класса от реализации делает код более читаемым.

Накатал большой пост, а потом подумал:

Зачем публиковать?   
У дядей интересные погремушки.   
Пусть ИГРАЮТСЯ!
anonymous
()
Ответ на: комментарий от alysnix

Модула-2 как раз и есть наследник Паскаля. Ещё такой нишевой ЯП, как оракловый PL/SQL, где есть объявление пакета и собственно пакет. И если я не ошибаюсь, у них это заимствовано из Ады (тоже паскалеподобный язык).

hobbit ★★★★★
()
Ответ на: комментарий от hateyoufeel

Почему неизбежно? Я её в 90% случаев успешно избегаю. И это другая проблема C++, потому что кто-то до сих пор не может забыть про однопроходные компиляторы из 70х.

тогда компилятору нужен лишний проход только для компиляции определений, как минимум…

принцип - «используется только то, что ранее декларировано» - способствует лучшей защите от случайных ошибок, скорости компиляции и простоте компилятора. я б от него не отказывался.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

тогда компилятору нужен лишний проход только для компиляции определений, как минимум…

При использовании template, макросов, … он все равно нужен …

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.