Неоднозначная ситуация с функцией преобразования в классе

Тема в разделе "LANGS.C", создана пользователем Ronin_, 2 июн 2017.

  1. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Ох уж эти плюсы. Не используйте перегрузку операторов. Вернее, делайте это в крайнем случае.
     
  2. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Ох уж эти неосиляторы. Не слушайте их нытьё. Вернее, делайте это в крайнем случае.
     
  3. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Вообще-то, то, что вы привели:
    Это полное свинство.
    Вполне очевидно, что в этом случае:
    1. Поведение компилятора кардинально зависит от платформы.
    2. Мы должны прибегнуть к условной компиляции (макросам), которые самим же Страуструпом преданы анафеме (читать: "макросы - зло").
    3. Перегрузка operator + приводит к массе неочевидных действий со стороны компилятора. Возникает особая магия.
    4. Поведение языка относительно перегруженных operator'ов сильно зависит от производителя компилятора и его версии.

    Так что неосиляторам ####, они смотрят на плюсоидов как на потенциальных самоубийц.
     
    Последнее редактирование модератором: 13 июн 2017
  4. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    топикстартер добавил Num::operator const char*() чисто for fun; он не нужен для этого класса. Убрать его — и проблем нет.
    Да, это заметно. Неосиляторы уже не в первый раз пытаются тут намекнуть, КАК и НАСКОЛЬКО им #### на C++ и на этот тред. Прям как тут.
    Осталось в личку начать писать об этом.
     
    Последнее редактирование модератором: 13 июн 2017
  5. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Это, наверное, потому что неосиляторы уже наелись того дерьма, которое вы возводите в абсолют и, больше не желая в него окунуться, используют плюсы очень осторожно и очень ограниченно. Чего и остальным советуют.
     
    Последнее редактирование модератором: 13 июн 2017
    DelAlt нравится это.
  6. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Я тут допустил небрежность в формулировке. В overload resolution он, конечно, участвует, но исключается из кандидатов по указанной причине.
     
  7. Ronin_

    Ronin_ Active Member

    Публикаций:
    1
    Регистрация:
    24 дек 2016
    Сообщения:
    252
    CurryHowardIsomorphism, SadKo, проще поступил, перегрузил плюс явно когда в операции справа от плюса целочисленный литерал, для таких операций как умножение уже вызывается функция преобразования.
     
  8. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Ronin_, так а что там с MinGW? ;)
     
  9. Ronin_

    Ronin_ Active Member

    Публикаций:
    1
    Регистрация:
    24 дек 2016
    Сообщения:
    252
    CurryHowardIsomorphism, если вы про g++ из пакета TDM GCC, то и там все работает.

    SadKo, Не согласен с вами.
     
    Последнее редактирование модератором: 13 июн 2017
  10. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Ваше право. Я тоже использую плюсы, но очень аккуратно и ограниченно.
     
  11. Ronin_

    Ronin_ Active Member

    Публикаций:
    1
    Регистрация:
    24 дек 2016
    Сообщения:
    252
    SadKo, Аккуратно и ограниченно, это как?
     
    Последнее редактирование: 13 июн 2017
  12. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Например, не использовать RAII и исключения.
     
  13. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Вангую, SadKo хотел написать RTTI
    но не осилил
     
  14. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Нет, именно RAII. Хотя, в C++ от RTTI также почти никакого толку.
    Оппа, похоже кто-то сел в лужу.
    Фанбой от С++ не знает, что такое паттерны проектирования.
     
    Последнее редактирование: 14 июн 2017
  15. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Т.е. никакими стандартными контейнерами, строками и т.д. не пользуешься? Сильно.
     
  16. Ronin_

    Ronin_ Active Member

    Публикаций:
    1
    Регистрация:
    24 дек 2016
    Сообщения:
    252
    SadKo, Как вы без RTTI будете идентифицировать объект по его типу во время выполнения программы?
     
    Последнее редактирование: 14 июн 2017
  17. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    Ronin_, Свой "ртти" с блекжеком и шл!!!ами )) ну или типа того :)
     
  18. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Чтобы они мне хорошо так поднагенерили бинарного кода? История со строками вообще доставляет. В каждом тулките своя реализация. Поэтому смысла пользовать монструозный std::string и нет никакого.
    А оно надо? Для меня RTTI - это нечто большее, чем идентификация объекта по типу. Например, рефлексия. А без рефлексии RTTI особо и не нужен.
    Ну так без нормальной рефлексии то на то и приходится. Динамически инстанцировать объект произвольного класса в С++ и сериализовать/десериализовать его в произвольный формат? Не, не слышали.
     
  19. Ronin_

    Ronin_ Active Member

    Публикаций:
    1
    Регистрация:
    24 дек 2016
    Сообщения:
    252
    ~20%? Не так уж это и много. STL очень богатая библиотека и много новшеств там.

    Простой пример с линейным списком, лямбда выражением и циклом по диапазонам.

    Код (C++):
    1.  
    2.  list<string> l = {"C", "C++", "Python", "Javascript", "SQL", "PHP"};
    3.  
    4.     l.remove_if([=](string s) {return s == "PHP";});
    5.     for(auto elt: l) cout << elt << ' ';
    6.     cout << '\n';
    7.  
    Или например простой пример с map:

    Код (C++):
    1.  
    2.  map<string, int> care;
    3.  
    4.     care.insert(make_pair("porsche", 403));
    5.     care.insert(make_pair("vaz", 185));
    6.     care.insert(make_pair("dodge", 411));
    7.  
    8.     map<string, int>::iterator ptr = care.begin();
    9.  
    10.     while(ptr != care.end()) {
    11.         cout << "name: " << ptr->first << " speed: " << ptr->second << endl;
    12.         ptr++;
    13.     }
    14.  
    Попробуйте своё написать, без STL. Интересно будет посмотреть.

    Какого характера вы решаете задачи, от этого нужно и отталкиваться в надобности.

    И ещё интересно как вы без исключений выживаете?
     
    Последнее редактирование: 15 июн 2017
  20. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    STL достаточно ужасен. Достаточно посмотреть на коллекции в других языках и понимаешь, что это ужас-ужас.
    Ну и опять же, смотрите. Если я буду использовать два таких контейнера:
    Код (C++):
    1.  
    2. std::vector<std::string> v1;
    3. std::vector<const std::string> v2;
    4.  
    То плюсы нагенерят мне аж целых две пачки дублирующихся функций, которые будут делать одно и то же.

    А теперь давайте посчитаем, сколько раз в этом случае будет дёргаться Heap. Предсказуемо? Неа, implementation-dependent.

    Охренеть. Почему-то в других нормальных языках у контейнеров типа map есть метод put(key, value), что исключает необходимость конструировать пару при помощи make_pair, и, как следствие, заставлять компилятор лишний раз напрягаться с оптимизациями. Почему разработчики STL до этого не додумались, остаётся секретом. Наверное, из-за их латентной привязанности к BDSM.

    Есть у меня ряд коллекций, которые имеют достаточно юзабельный интерфейс и не сжирают тонны места в секции кода.
    Давайте представим работу с указателями, то есть ситуацию, когда вам нужно просто хранить указатели в коллекции. Такая коллекция будет работать
    одинаково в большинстве случаев. Однако когда мы попытаемся сделать:
    Код (C++):
    1.  
    2. std::vector<void *> a;
    3. std::vector<char *> b;
    4. std::vector<float *> c;
    5. a.push_back(some_void_ptr);
    6. b.push_back(some_char_ptr);
    7. c.push_back(some_float_ptr);
    8.  
    Мы получим три одинаковых функции, сгенерированнных в секции кода. В то время как подход к хранению указателей можно всегда генерализовать.
    Вы, конечно, сейчас начнёте кидаться в меня тапком и кричать, что надо юзать shared_ptr или unique_ptr вместо чистых указателей, но на это у меня также есть аргумент: их использование должно быть обосновано. Например, при попытке изменить shared_ptr в multithreaded-среде вы постоянно будете дёргать спин-блокировки, а отсюда получим резкое проседание производительности, т.к. процессор со спин-блокировками работает раз в 5-10 медленнее, чем с обычной памятью.

    Вот именно, прежде чем заюзать STL или исключения (к слову, местопроисхождение которых сложно выяснить, так как в С++ даже при наличии RTTI(C)(R)(TM) мы банально не можем получить стектрейс до места, откуда эти самые исключения были кинуты), надо серьёзно задуматься: а нужно ли мне это. Например, если мне нужно работать с файлами (а это либо C-функции fopen, fclose и т.д. либо системные вызовы open, close и т.д.), то для С++-адептов нормой считается обернуть это всё в класс, который будет открывать файл по конструктору, а закрывать по деструктору (смотрим на ifstream/ofstream и плачем). При этом, почему-то забывается и игнорируется тот факт, что close и fclose также могут возвращать ошибку, и эту ситуацию тоже нужно уметь в определённых случаях корректно обрабатывать. Что же можно сделать в деструкторе? Кинуть исключение? Нет, это опасно и приводит к UB. Изменить состояние объекта, пометив его невалидным? Нет, потому что после вызова деструктора память, занятая объектом, освобождается. Ну вы поняли, к чему я клоню: так восхваляемая концепция RAII, возведённая плюсоидами в абсолют (да настолько, что плюсоиды сопротивляются всем добрым и недобрым просьбам ввести в try-catch блок поддержку finally), здесь отсасывает по-полной программе.

    А вы попробуйте провести эксперимент. Напишите какую-нибудь простенькую программу и скомпилируйте её с ключиком -fno-exceptions. Думаю, через пару дней у вас уже выработается стиль написания exception-aware кода.
     
    TermoSINteZ нравится это.