Из центральной части Канады — на юго-запад США! Альбукерке расположен в штате Нью-Мексико:



На встрече международного комитета по стандартизации C++, которая прошла в этом городе, приняли одно очень большое нововведение в С++20 и несколько маленьких.

operator <=>


В черновик C++20 был добавлен оператор spaceship, с помощью которого можно за одну операцию определять отношение элементов. В простых случаях это значит, что можно определить оператор spaceship и ваш класс научится сравниваться любыми способами: <, >, <=, >=, == и !=. Пример:
Без оператора spaceship С оператором spaceship
struct point3d {
    int x;
    int y;
    int z;
};

using p_ref = const point3d&;

bool operator==(p_ref a, p_ref b) {
    return a.x == b.x
        && a.y == b.y
        && a.z == b.z
    ;
}
bool operator< (p_ref a, p_ref b) {
    return a.x < b.x
        || (a.x == b.x && a.y < b.y)
        || (a.x == b.x && a.y == b.y
            && a.z < b.z)
    ;
}

bool operator!=(p_ref a, p_ref b) {
    return !(a == b);
}
bool operator<=(p_ref a, p_ref b) {
    return !(b < a);
}
bool operator> (p_ref a, p_ref b) {
    return b < a;
}
bool operator>=(p_ref a, p_ref b) {
    return !(a < b);
}

struct point3d {
    int x;
    int y;
    int z;

    auto operator<=>(const point3d&)
        const = default;
};
Поведение оператора можно настраивать типом возвращаемого значения:

class weak_equality;
class strong_equality;
class partial_ordering;
class weak_ordering;
class strong_ordering;

Кроме того, можно писать тело самого оператора, если вам необходимо какое-то особое поведение:

#include <compare> // weak_ordering, is_neq

struct point3d {
    int x;
    int y;
    int z;

    std::weak_ordering operator<=>(const point3d& p) const {
        using std::abs;
        if (auto cmp = abs(z) <=> abs(p.z); std::is_neq(cmp)) return cmp;
        if (auto cmp = abs(x) <=> abs(p.x); std::is_neq(cmp)) return cmp;
        return abs(y) <=> abs(p.y);
    }
};

Описание поведения оператора и примеры использования можно найти в этом документе. Интеграция spaceship со стандартной библиотекой описана здесь*.

Особенно приятно видеть, что добавили следующий алгоритм:

lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2);

Теперь можно эффективно, в один проход, сравнивать диапазоны данных.

osyncstream


Многие из читателей наверняка писали в std::cout/std::cerr из нескольких потоков одновременно и видели странный вывод:

#include <iostream>
#include <thread>
#include <string_view>

void say_hello(std::string_view username) {
    std::cerr << "Hello " << username;
}

void beware_of(std::string_view something) {
    std::cerr << something << " is dangerous";
}

int main() {
    std::thread t1([]{
        say_hello("Rachel");
    });

    std::thread t2([]{
        beware_of("darkness");
    });

    std::cerr << '\n';
 
    t2.join();
    t1.join();

    /* Possible output:
            Hello darkness
            Rachel is dangerous
    */
}

Так вот, в C++20 добавили классы, которые позволяют легко и без лишних накладных расходов избежать перемешивания выводов:

#include <iostream>
#include <thread>
#include <string_view>

void say_hello(std::string_view username) {
    std::osyncstream{std::cerr} << "Hello " << username;
}

void beware_of(std::string_view something) {
    std::osyncstream(std::cerr) << something << " is dangerous";
}

int main() {
    std::thread t1([]{
        say_hello("Rachel");
    });

    std::thread t2([]{
        beware_of("darkness");
    });

    std::cerr << '\n';
 
    t2.join();
    t1.join();
}

Подробности — в этой бумаге*.

Заслуги РГ21


Мы, как всегда, ездили на заседание с несколькими предложениями:

  • P0539R2 — integers, размер (количество байт) которых задаётся на этапе компиляции. В интерфейсе решили использовать биты, посоветовали разбить бумагу на несколько бумаг поменьше, обсуждали исключения и причие мелочи. Нужно обновлять proposal.
  • P0415R0* — constexpr для std::complex. Приняли в C++20 и прямо на месте пометили ещё пару функций как constexpr.
  • P0202R2* — constexpr для большинства алгоритмов в <algorithm>. Бумагу разделили на две части и приняли в C++20 ту часть, в которой идёт речь об алгоритмах алгоритмы, не использующих std::swap. Оставшуюся часть примут на следующих заседаниях, будет отдельный proposal.
  • P0275R2 — shared_library или классы, необходимые для динамической загрузки библиотек. Рассмотрели в группе Evolution, решили, что бумага затрагивает только стандартную библиотеку и допустимо оставить поведение плагинов не специфицированным. Дальнейшая работа будет происходить в группе Library Evolution на следующих заседаниях.
  • P0858R0 (ещё не выложили в открытый доступ) — эту бумагу написали прямо во время встречи в Альбукерке. Бумага позволяет работать с итераторами std::basic_string_view и std::array в constexpr контекстах. На следующем заседании собираются принять в C++20.

Вдобавок нас попросили представить комитету два предложения, непосредственно над написанием которых мы не работали:

  • P0457R1 — starts_with и ends_with для строк. Приняли в C++20. Шикарная штука!
  • P0458R0 — функция contains(key) member для классов [unordered_]map/set/multimap/multiset. Отправили в LWG, на следующем заседании, возможно, примут в C++20.

Прочие новинки


  • range based for теперь может иметь следующий инициализатор:

    for (T thing = f(); auto& x : thing.items())
  • Отныне можно конструировать лямбды без состояния:

    using greater_t = decltype([](auto x, auto y) { return x > y; });
    std::map<std::string, int, greater_t> map;
    constexpr greater_t comparator{}; // OK
  • std::is_pod и std::is_pod_v помечены как deprecated.
  • Добавили новый type trait std::remove_cvref.
  • Атрибут [[nodiscard]] добавили к функциям async(), new, allocate(), empty() и launder().
  • std::memory_order* теперь доступны в виде scoped enum.
  • Добавили атомарные умные указатели:

    template <class T> struct atomic<shared_ptr<T>>;
    template <class T> struct atomic<weak_ptr<T>>;
  • Добавили поддержку чисел с плавающей точкой в std::atomic.
  • Множество мелких улучшений и багфиксов.

Параллельно кипела работа по подготовке к Modules TS и были добавлены множественные небольшие улучшения для Networking TS.

Вместо итогов


У вас есть идеи для C++20? Нашли проблемы в C++17, 14 или 11? Просто хотите подстегнуть разработку той или иной фичи C++? Заходите на сайт рабочей группы: stdcpp.ru. Добро пожаловать!

Есть желание помочь с написанием предложений и внести своё имя в историю? Мы подготовили мини-инструкцию по написанию предложений.

27 ноября состоится встреча РГ21, где будет телемост с Гербом Саттером и несколько выступлений. Приходите — вот ссылка на регистрацию. Наконец, готовится встреча C++ User Group в Нижнем Новгороде.


* Во всех этих случаях в стандарт приняли несколько обновлённые версии.

Комментарии (241)


  1. KivApple
    22.11.2017 15:43

    Что насчёт resumable functions?


    1. antoshkka Автор
      22.11.2017 16:53

      Есть в виде TS, почитать можно вот тут.

      Как обкатают, станут частью стандарта.


      1. KivApple
        22.11.2017 23:43

        Это то я знаю. Но войдёт ли в C++20 или надо ждать ещё дольше?
        И когда им научатся компиляторы отличные от MSVC? (многие фичи начинают поддерживаться раньше выхода стандарта, а тут никто кроме MSVC не торопится)


        1. khim
          23.11.2017 00:07

          Это то я знаю. Но войдёт ли в C++20 или надо ждать ещё дольше?
          Этого вам никто не скажет до выхода стандарта. Истории с std::async хватило.
          И когда им научатся компиляторы отличные от MSVC? (многие фичи начинают поддерживаться раньше выхода стандарта, а тут никто кроме MSVC не торопится)
          Вот именно в этом — и проблема: на платформах, отличных от Windows, это никому не интересно (по разным причинам). А Windows-only технологию вряд ли удастся пропихнуть в стандарт.

          С другой стороны альтернативное предложение (которое мне лично нравится гораздо больше) вроде как заглохло, так что может быть и примут… но не факт, что в C++20.


          1. quasilyte
            23.11.2017 17:42

            > Истории с std::async хватило.

            Можете либо уточнить, что имели в виду, а ещё лучше, предоставить сслыку, если там какой-то разбор фатального недостатка, пожалуйста?
            Или всё довольно банально и `std::async` просто откладывался несколько раз?


            1. khim
              23.11.2017 18:15

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

              Или всё довольно банально и `std::async` просто откладывался несколько раз?
              Наоборот — его «по-быстрому» включили в стандарт… теперь расхлёбывают…

              Если коротко, то оказалось что std::async в том виде, в каком он стандартизован использовать практически невозможно — хотя можно использовать вариации реально реализованные разными вендорами опираясь на вещи не описанные в стандарте.

              Когда Microsoft выкатил своё предложение, то оказалась, что там — та же фигня: реализация ровно того, что они предложили не позволяет писать работающие программы, а то, что реально реализовано в MSVC — опирается на некоторые вещи, которые в стандарте не упоминаются.

              Кому и зачем такой стандарт нужен? C++ — это ж не OOXML, который был нужен Microsoft'у, чтобы продавать офис в некоторых странах, расширения, которые нельзя использовать без учёта специфики конкретной реализации, вполне себе могут жить и вне стандартарте без формального «окропления водой» комитетом по стандартизации.

              Посему было решено подождать пока будет ещё хотя бы одна реализация… но только оказалось, что это никому, кроме Microsoft'а не интересно — а в таком случае… зачем спешить?


  1. ZaMaZaN4iK
    22.11.2017 16:01
    +1

    Модули успевают к C++20?


    1. antoshkka Автор
      22.11.2017 18:03

      Пока только готовятся к выходу в виде TS. Непонятно как оно пойдёт дальше. Concepts прожили два года в виде TS, прежде чем их втянули в C++20.


  1. reversecode
    22.11.2017 16:18

    Знаете что меня огорчает?
    Открываем любой сайт вакансий С++
    Одна из строк требования — знание языка С++ (C++98, C++03, C++11, C++14, С++-20)
    Да да 20 я уже и такое встречал
    Я понимаю это могут быть глупые хр которые возможно копипастят, но наверняка разнарядка приходить для них сверху
    И потом на собеседовании тебя начинают спрашивать, а в чем тонкость вот этой версии от той, а в какой версии появилось тото тото…
    Читаем ченж логи новых стандартов, то..., это..., итд добавили, это… депрекейдет или удалили
    Язык С++ превращается в язык версий С++


    1. ZaMaZaN4iK
      22.11.2017 16:19

      То, как HR пишут вакансии, к самому языку никак не относится.

      В язык обычно что-то добавляют. Удаляют очень и очень редко. В комитете стараются тщательно следить за обратной совместимостью.


    1. vanxant
      22.11.2017 16:36
      +1

      Хр упоротые курицы, не обращайте внимания на их писанину. Просто ищут зеакомые буквы, все.
      А вот потрындеть о состоянии языка на собеседовании — милое дело. Сразу видно, что у человека болит и, соответственно, чем он на самом деле плотно пользовался.


    1. DistortNeo
      23.11.2017 01:21

      На самом деле, единственное принципиальное изменение произошло в C++11 — move semantics. Всё остальное — синтаксический сахар, который изучается напрямую на практике.


      1. F0iL
        23.11.2017 09:24

        Новую модель памяти я бы никак синтаксическим сахаром не назвал.


        1. DistortNeo
          23.11.2017 10:24
          -1

          Я что-то упустил? Поясните, что за новая модель памяти имеется в виду. Или вы стандартизацию multi-threading имеете в виду? Так это не новая модель памяти, а именно стандартизация того, что компиляторы де-факто и так делали.


          1. F0iL
            23.11.2017 10:59

            Да, связанные с порядком операций, например

            §6.7 [stmt.dcl] p4

            If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.

            и всякое другое.

            «Де-факто» и «де-юре» в данном случае играет роль, т.к. в первом варианте вам вообще никто ничего не гарантирует и нужно это учитывать.


            1. DistortNeo
              23.11.2017 11:57

              Я все равно не считаю принципиальным изменением переход от «де-факто» к «де-юре».

              А вот введение move-семантики затронуло сами принципы написания С++ кода.


              1. Gorthauer87
                23.11.2017 13:09

                Без афинных типов это хороший способ прострелить себе ногу.


        1. antoshkka Автор
          23.11.2017 10:24

          Сомневаюсь, что фишки новой модели памяти люди применяют в повседневном программировании.


          1. F0iL
            23.11.2017 10:55

            Например, возможность создать потокобезопасный синглтон простым static-полем без double-check locking, не?


            1. antoshkka Автор
              23.11.2017 11:26

              Это отдельная фишка. На неё была отдельная бумага www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2148.html


            1. DistortNeo
              23.11.2017 11:50

              Ни разу не было необходимости этого делать.
              Кстати, почему обычное статическое поле вы называете синглтоном?


              1. Antervis
                23.11.2017 12:28

                Есть так называемый «синглтон Майерса»:

                T &instance() {
                    static T instance;
                    return instance;
                }
                

                Он пишется меньшим количеством кода и сам заботится о потокобезопасности.


                1. Kobalt_x
                  23.11.2017 12:41

                  Если этот объект что-то инжектить в себя из других разделяемых библиотек с с static T instance есть большой шанс прострела ноги


              1. F0iL
                23.11.2017 12:33

                Если у вас ни разу не было в этом необходимости, то это не значит, что ваш опыт релевантен абсолютно для всех :)
                Обычное статическое поле — это не синглтон. Статическое поле может использоваться как хранилище для инстанса в простой потокобезопасной реализации синглтон-класса на C++11, в старых версиях стандарта же для этого нужна блокировка с двойной проверкой и барьерами памяти.


                1. DistortNeo
                  23.11.2017 16:25

                  Если у вас ни разу не было в этом необходимости, то это не значит, что ваш опыт релевантен абсолютно для всех :)

                  Так и есть. У меня, например, подобные статические поля являются ещё и thread_local.


            1. 0xd34df00d
              23.11.2017 19:33

              Double-check locking с точки зрения стандарта тоже ничего не гарантировал, кстати. Была забавная статья Александреску на эту тему.


              1. khim
                23.11.2017 21:35

                Вопрос не в статьях Александреску, а в MSVC.

                На практике-то double-check locking — работал. А инициализация глобалов — не работала. Теперь — работает и в теории и на практике. Хорошо же.


      1. 0xd34df00d
        23.11.2017 19:35

        constexpr-функции тоже не совсем сахар.

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


        1. khim
          23.11.2017 21:39

          Вообще провести границу между «сахаром» и «несахаром» тяжело. Какие-нибудь variadic template'ы — вроде как сахар, а без него многие вещи оччччено тяжко делаются.

          А уж квантовые переменные с «Редукцией фон Неймана» — это вообще непонятно куда отнести. Вроде как сахар, а реально — на этом можно такие вещи построить, которые без них вообще фиг сделаешь. С Boost.Hana поиграйтесь — очень весело…


          1. 0xd34df00d
            24.11.2017 04:31

            Какие-нибудь variadic template'ы — вроде как сахар, а без него многие вещи оччччено тяжко делаются.

            Ну, всякие вещи от boost.variant до наркомании в MPL/Fusion вполне в довариадиковые времена успешно делались. С вариадиками и всякими boost.hana приятнее, конечно.

            Вроде как сахар, а реально — на этом можно такие вещи построить, которые без них вообще фиг сделаешь. С Boost.Hana поиграйтесь — очень весело…

            Я с ханой не сильно много игрался, но довольно много чего делал сам, и там variable templates экономили максимум что пару скобочек, фигурных али круглых. Хотя с ними красивше выглядит, конечно.


            1. khim
              24.11.2017 05:27

              Я с ханой не сильно много игрался, но довольно много чего делал сам, и там variable templates экономили максимум что пару скобочек, фигурных али круглых.
              Вы с variadic templates не путаете? Попробуйте без них написать функцию, которая принимает произвольный список типов и для каждого типа — свой обработчик.

              Вот что-то подобное:
              #include <boost/hana.hpp>
              #include <boost/hana/ext/std/tuple.hpp>
              
              namespace hana = boost::hana;
              
              auto handlers = hana::make_map(
                hana::make_pair(hana::type_c<int>,
                                [](int i){ printf("0x%04x\n", i);}),
                hana::make_pair(hana::type_c<double>,
                                [](double g){printf("%10.2g\n", g);})
              );
              
              template<typename Tuple, typename Handlers>
              void handle(Tuple tuple, Handlers handlers) {
                hana::for_each(tuple, [handlers](auto o){
                  handlers[hana::type_c<decltype(o)>](o);
                });
              }
              
              int main() {
                auto tuple = std::make_tuple(1, 2.0);
                handle(tuple, handlers);
              }


              1. 0xd34df00d
                24.11.2017 07:26

                Вы про hana::type_c<int>? Ну напишу вместо этого hana::type<int> {}, проблем-то.

                У каждой variable template есть тип, и в неэзотерическом коде он вряд ли будет невыговариваемым.


                1. khim
                  24.11.2017 16:43

                  Вы про hana::type_c<int>?
                  Я про то, что вы можете передать hana::type_c<int>туда, куда нужно передавать переменную. В частности — можете сопоставить тип и что-то вычисляемое (массив какой-нибудь).

                  Ну напишу вместо этого hana::type<int> {}, проблем-то.
                  Проблемы таки возникнут. Потому что: The actual representation of hana::type is implementation-defined. In particular, hana::type may be a dependent type, so one should not attempt to do pattern matching on it.

                  У каждой variable template есть тип, и в неэзотерическом коде он вряд ли будет невыговариваемым.
                  Вопрос не в «выговариваемости». Вопрос, как я уже сказал, в «корпускулярно-волновом дуализме». Variable template — это всё-таки variable. Она одна (пусть и неизвестно какой у неё тип). Её можно менять как угодно, передавать куда угодно и вообще — работать с ней как с переменной. hana::type<int> {} же — это один из обьектов с определёнными свойствами. Что очень и очень усложняет работу с ними.

                  P.S. Так-то вообще всё, что вы делаете можно в brainfuck отобразить. И сказать, что ни в одном языке программирования ничего, кроме «сахара» для brainfuck'а-то и нету.


                  1. 0xd34df00d
                    24.11.2017 20:45

                    Я про то, что вы можете передать hana::type_c<int>туда, куда нужно передавать переменную.

                    Так можно же передать и hana::type<int> {}

                    Проблемы таки возникнут.

                    Это связано с конкретной реализацией и с тем, что в API торчит variable template, дабы у автора была некоторая свобода манёвра. Давайте эту сегодняшнюю реализацию зафиксируем и будем её рассматривать.

                    Она одна (пусть и неизвестно какой у неё тип).

                    Это не гарантирует отсутствия других экземпляров того же типа. Да и операторы сравнения всё равно писать придётся для типа, если вы захотите в какой-нибудь контейнер её класть. Либо не придётся, но это всего лишь значит, что вы сравнение кодируете в типе, и вам снова variable templates не сказать чтоб нужны.

                    Её можно менять как угодно

                    Вы про это?

                    #include <iostream>
                    
                    template<typename T>
                    T smth = 10;
                    
                    int main()
                    {
                        std::cout << smth<int> << std::endl;
                        std::cout << smth<double> << std::endl;
                        
                        smth<int> = 20;
                        smth<double> = 30;
                        
                        std::cout << smth<int> << std::endl;
                        std::cout << smth<double> << std::endl;
                    }
                    


                    Нууу… Можно сделать и обычной шаблонной функцией, возвращающей ссылку на локальный static-объект нужного типа. Собственно, как и hana::type_c. Как и вообще оно зачастую делалось до появления variable templates. Да, требует пары лишних скобочек в точке вызова и пары лишних строк кода в точке определения, но я бы не сказал, что их экономия — это настолько существенное нововведение.

                    Что очень и очень усложняет работу с ними.

                    До сих пор не вижу, как.

                    P.S. Так-то вообще всё, что вы делаете можно в brainfuck отобразить. И сказать, что ни в одном языке программирования ничего, кроме «сахара» для brainfuck'а-то и нету.

                    Это верно. Сахарность точным объективным образом не измеришь.


      1. vlanko
        24.11.2017 12:19

        std::thread


    1. lookid
      23.11.2017 10:40

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


      1. 0xd34df00d
        23.11.2017 19:37

        Зависит. Из последнего меня просили, например, написать аналог std::any с такими-то требованиями к конвертации типов вверх-вниз-вбок по иерархии, или наваять парсер JSON-подобного языка (в итоге получилось что-то комбинатороподобное на манер attoparsec).

        Потом за системы типов и раст поболтали.


  1. sinc
    22.11.2017 16:48

    auto operator<=>(const point3d&)
        const = default;
    

    зачем такая ужасная конструкция в языке? а default = const будет работать?


    1. antoshkka Автор
      22.11.2017 16:49

      В одну строчку просто не поместилось в табличке:

      auto operator<=>(const point3d&) const = default;


      1. humbug
        23.11.2017 02:05

        Кроме того, можно писать тело самого оператора, если вам необходимо какое-то особое поведение:

        #include <compare> // weak_ordering, is_neq
        
        struct point3d {
            int x;
            int y;
            int z;
        
            std::weak_ordering operator<=>(const point3d& p) const {
                using std::abs;
                if (auto cmp = abs(z) <=> abs(p.z); std::is_neq(cmp)) return cmp;
                if (auto cmp = abs(x) <=> abs(p.x); std::is_neq(cmp)) return cmp;
                return abs(x) <=> abs(p.x);
            }
        };

        В вашем 'особом' поведении закралась бага.


        antoshkka лучше скажи, когда откроете сорцы libgeobase, я бы переписал на Rust.


        1. antoshkka Автор
          23.11.2017 09:52

          Спасибо, пример немного подправил.

          А насчёт geobase — это не ко мне :)


      1. FadeToBlack
        23.11.2017 14:41
        -1

        у меня такое ощущение, что std пишут на терминалах в 40 строк, а вместо большинства клавиш там "_". есть еще мнение, что std пишут роботы


  1. sitev_ru
    22.11.2017 16:58
    +1

    C++20 — учить 20 лет, перед тем как приступить к программированию ))


    1. antoshkka Автор
      22.11.2017 17:15

      По хорошему C#, Java и PHP нужно учить столько же, прежде чем приступать к программированию :)


      1. FadeToBlack
        23.11.2017 14:42
        -3

        По всей видимости, вы на самом деле никогда не программировали на C++, если пытаетесь так наивно сравнивать.


    1. khim
      22.11.2017 18:38
      +1

      А что в этом такого ужасного? Какого-нибудь архитектора учат несколько лет — причём большая часть этого посвящена умению оформлять чертежи. Для того, чтобы врачу разрешили оперировать — нужно тоже учиться несколько лет и потом ещё практиковаться под руководством опытных наставников. И опять-таки: латынь и умение грамотно оформлять всё — большая часть процесса…

      И только в IT считается, что двухмесячных курсов должно быть достаточно для того, чтобы претендовать на зарплату, которая будет выше, чем у начинающего архитектора или терапевта.


      1. tirinox
        23.11.2017 09:18

        Представь, что в 2017 ты начинаешь учить С++17, через 3 года с гордостью заканчиваешь его. И бац! С++20. Опять надо учить, опять ты никому не нужен.

        В IT все меняется с каждым годом все быстрее. Поэтому пора изобретать принципиально новые подходы к программированию и его обучению. Да, за 2 месяца С++ не выучить, но зато можно выучить другой какой-то язык. Мне кажется, не за горами тот год, когда мы начнем писать программы на своем естественном языке с нормальным уровнем абстракции без этих spaceship default const.


        1. Free_ze
          23.11.2017 12:27

          И бац! С++20. Опять надо учить, опять ты никому не нужен.

          Чай, не джаваскрипт) Вряд ли кому-то откажет работодатель по причине того, что кандидат не в совершенстве освоил новый стандарт. Тем более, что первые пару лет еще придется поискать конторы, которые начнут его применять.
          Как тут уже верно замечали, действительно концептуальное изменение было одно — семантика перемещения в C++11 (спустя 7 лет от предыдущего стандарта), всё остальное — сахар, который усваивается прямо по ходу дела.


    1. NafFiQ
      23.11.2017 11:35

      Мне очень понравилась одна речь дяди Боба на тему разработки ПО (правда сама лекция была о SOLID).
      > Кол-во разработчиков увеличивается вдвое каждые 5 лет. Соответственно половина разработчиков ПО имеют < 5 лет опыта в бою.

      Еще в другой речи о будущем программирования он освещает тему важности качественно написанного кода. От некоторых программ зависят жизни миллионов человек. И 20 лет опыта вполне нормальная цифра при такой ответственности.


      1. sena
        23.11.2017 13:47
        +1

        Неужели это правда, что количество разработчиков за 5 лет в 2 раза увеличивается? Где почитать статистику?


        1. NafFiQ
          24.11.2017 15:54

          Не проверял, к сожалению, слова Боба Мартина, но вот видео с выступлением (время стоит как раз но том моменте, о котором я упоминал)


        1. NafFiQ
          24.11.2017 16:00

          Самому стало интересно и нашел таки более подробную статистику http://blog.cleancoder.com/uncle-bob/2014/06/20/MyLawn.html

          Спасибо, что подогрели мой интерес :)


          1. sena
            24.11.2017 18:29

            По ссылке интересная статья, но едва ли по ней можно сказать что и сегодня количество удваивается каждые 5 лет. Он берёт количество программистов в 1974, потом сравнивает с 2014, для целей его статьи это нормально. Но предполагать что скорость роста остаётся неизменной и сегодня, только на основании этих данных, было бы неверным. Для того чтобы знать, что происходит сегодня, надо посмотреть статистику последних лет.


  1. mfedyashov98
    22.11.2017 17:15

    В наш любимый С++ стали добавлять, возможно, крутые фичи, но на мой взгляд они совершенно ему не нужны(за исключение возможно <=>). С++, на мой субъективный взгляд, один из самых интересных и сложных языков, поэтому не следует его так сильно загружать. Я бы добавил возможности связанные с графикой, что бы начинающим (и не только) стало легче и интереснее работать с этим языком


    1. ZaMaZaN4iK
      22.11.2017 17:53

      Какие фичи на Ваш взгляд никому не нужны?

      Никто не мешает Вам как разработчику на С++ использовать только какое-то подмножество языка и не изучать все его тонкости и дебри. Это совершенно ни к чему.

      Рассматривается потихоньку пропозал насчёт графики.


      1. cuwHuk
        23.11.2017 09:35

        Никто не мешает Вам как разработчику на С++ использовать только какое-то подмножество языка и не изучать все его тонкости и дебри. Это совершенно ни к чему.

        1. Подходит на 100% в случае разработки приложения в одиночку с использованием только стандартной библиотеки.
        2. В команде уже начинаются сложности, но в целом их можно преодолеть разработав собственные инструкции, которых все должны строго придерживаться. Но это уже потенциальная проблема от простого недовольства до принципиального отказа работать в команде.
        3. Но как насчёт сторонних библиотек? Как заставить их авторов придерживаться ваших правил?

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


    1. 0xd34df00d
      22.11.2017 18:39

      Концепты. Концепты, очень надеюсь, добавят. Помимо уже тысячу раз обсуждённых профитов, ad-hoc requirement clause'ы в сочетании с constexpr if позволяют просто чудеса творить: вместо условного

      template<typename T>
      using Detector = decltype(std::declval<T>().MakeFieldName(QString {}));
      
      template<typename T>
      QString MakeFieldName(const QString& str)
      {
          if constexpr (std::is_detected_v<Detector, T>)
              return T::MakeFieldName (str);
          else
              return str;
      }
      


      можно писать что-то вроде
      template<typename T>
      QString MakeFieldName(const QString& str)
      {
          if constexpr (requires (T t) { t.MakeFieldName(QString {}); })
              return T::MakeFieldName(str);
          else
              return str;
      }
      

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

      А, пользуясь случаем, нужны constexpr ternary operators, вот.


    1. laphroaig
      22.11.2017 18:47

      Такие сомнения высказываются с момента рождения c++. Но по мне так после десятилетий застоя уж шибко резво рванул развиваться, я не поспеваю )


    1. khim
      22.11.2017 18:50

      Я бы добавил возможности связанные с графикой, что бы начинающим (и не только) стало легче и интереснее работать с этим языком
      Вы хотите сказать «сложнее и попобольнее», как я понял.

      Я не видел ни одной библиотеки для работы с графикой, ни на одном языке программирования, которая была бы уместна и в программе на iOS и в программе для Windows и в программе под Android. Есть всякие кроссплатформенные вещи (типа той же Ауры), но опять-таки — игры на них делать не будешь.

      Пока что почти вся стандартная библиотека C++ устроена так, что её можно использовать в любом проекте под любую платформу. Графические вещи с этим же свойством — я представить себе не могу.

      P.S. Речь не идёт о том используются они или нет. Если проект достаточно старый — там и строки могут быть QT'шные (или свои собственные) и callback'и и прочее. Но в новом проекте — вполне можно использовать то, что входит в стандарт. И люди регулярно отказываются от своих «велосипедов». Представить себе графическую библиотеку с подобным свойством, я, увы, не могу.


      1. 0xd34df00d
        22.11.2017 19:16

        Кутешные строки в гуи-приложении всё-таки куда удобнее STL'ных, к слову. Даже с новыми startsWith/endsWith.

        А к гуям ещё локализация притащится, кстати, тоже веселуха будет. Не, не место GUI-либе в стандарте.


        1. Antervis
          23.11.2017 00:34

          строки Qt cow и utf16. Это не всегда уместно


          1. khim
            23.11.2017 03:13

            Я бы сказал сильнее: это вообще почти никогда не уместно. COW на современных системах только замедляет работу и почти не экономит память, а UTF-16… смысл в нём есть только, если вам вам нужно работать с legacy-кодом, который оказался таким из-за того, что кто-то когда-то решил, что всем хватит 640K все буквы поместятся в int16.

            Нет, я не спорю: QString — хорошая вещь… для того времени, когда она была написана… Но сегодня… лучше иметь библиотеку поверх std::string. Эх, если б только разработчики ICU не страдали фигнёй…


            1. sitev_ru
              23.11.2017 16:46

              Есть наброски: github.com/sitev/core/blob/master/src/strings.cpp
              правда сам писал)


            1. 0xd34df00d
              23.11.2017 19:40

              Иксы до сих пор не особо многопоточные, отрисовывать всё равно только из одного треда можно. Да и вообще в GUI-коде, вероятно, удобство API куда важнее производительности строк. Вы же не перелопачиваете гигабайты данных прям в гуях?

              UTF-16 действительно глупое решение, да.

              В принципе, есть ещё всякие boost.format, boost.algorithms, и так далее, но почему-то эту часть буста я патологически не переношу.


              1. khim
                23.11.2017 21:58

                Иксы до сих пор не особо многопоточные, отрисовывать всё равно только из одного треда можно.
                И именно поэтому COW — глупое решение. Читаем. Черно-зелёным написано: Qt, however, uses atomic reference counting to ensure the integrity of the shared data, avoiding potential corruption of the reference counter.

                Вы знаете сколько стоят атомики на современных многоядерных CPU?

                Да и вообще в GUI-коде, вероятно, удобство API куда важнее производительности строк.
                Ага. А в других местах — давайте использовать другие строки. Как Windows — разведём зоопарк и будем в них путаться потом.

                Вы же не перелопачиваете гигабайты данных прям в гуях?
                Не перелопачиваю. И тем страннее выглядит решение получить копеешную экономию памяти (да и то не факт: на практике за счёт того, что std::string для коротких строк память не выделяет потребление памяти может оказаться меньше, чем с QString'ами) за счёт существенного замедления простых операций.

                В принципе, есть ещё всякие boost.format, boost.algorithms, и так далее, но почему-то эту часть буста я патологически не переношу.
                Там тоже много странного, да. Сделать хорошие строки — весьма непросто, как показывает практики. Во всех языках и библиотеках — с ними те или иные проблемы. std::string с utf8 содержимым — не самый худший вариант, а с учётом того, что это, фактически, стандарт — стараюсь им и пользоваться.


      1. Kobalt_x
        23.11.2017 12:02

        Что там в STL работает на платформах без поддержки исключений, пара алгоритмов, std::is_* да std::array?


        1. antoshkka Автор
          23.11.2017 13:13

          Всё, но это не совсем C++.

          Поищите замечательные доклады от SG14 (game dev, low latency). Они пытаются уйти от исключений в сторону более быстрых механизмов сообщений об ошибках… И не могут найти механизмы, которые работали бы быстрее, в случае отсутствия ошибки.

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


          1. Kobalt_x
            23.11.2017 14:03

            Это замечательно но смысл не в перфомансе, есть платформы(микроконтроллеры, uefi, драйвера) где есть этот не совсем c++ т.е просто поддержка исключений в libstdc++ нет любой вызов throw приведет к ub(в терминах хост платформы). И тут мы приходим к выводу что либо запилите исключения ручками для рантайма сами, либо не трогайте STL либо откажитесь от всего синтаксического сахара и пишите на C.


            1. antoshkka Автор
              23.11.2017 14:08

              Что конкретно вы предлагаете исправить в стандарте? Вызывать std::terminate при throw на платформе без поддержки исключений?


              1. Kobalt_x
                23.11.2017 15:37

                Это сложный вопрос, ясно что stl уже не переписать, да и error_code методы будет нужно поддерживать, возможно когда какой-нибудь noexcept-like stl реализуют в boost можно будет говорить, а сейчас яcно это нужно 1.5 людям, у которых уже есть свои решения. Но в принципе std::terminate с backtraceом на таких платформах который вроде был в каком-то из предложений тоже бы не помешал)


                1. antoshkka Автор
                  23.11.2017 15:52

                  backtrace/stackrace на подходе, скоро закинем в комитет предложение.


            1. eao197
              23.11.2017 14:14

              STL — он же большой. Какие проблемы при отсутствии исключений вы ожидаете при использовании, скажем, std::find, std::count_if, std::transform, std::copy и др.?


              1. Kobalt_x
                23.11.2017 15:17

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


            1. 0xd34df00d
              23.11.2017 19:41

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

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



        1. Antervis
          23.11.2017 15:15

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


          1. Kobalt_x
            23.11.2017 15:27

            std::conditional_variable как проверить заранее что не бросят system_error во время вызова wait?


            1. Antervis
              23.11.2017 16:07

              в с++14 condition_variable::wait не кидает исключений


  1. eao197
    22.11.2017 19:16
    +1

    А вот такой вопрос, не очень связанный с содержимым статьи, но связанный с развитием C++: а на заседаниях комитета всплывают вопросы отсутствия в C++ де-факто стандартных средств управления зависимостями и/или средств сборки C++ проектов?

    Ну вот в том же Rust-е есть Cargo, которая снимает изрядную часть головной боли с растоманов. В C++ же все, такое ощущение, осталось неизменным с середины 80-х годов. Каждый волен извращаться как хочет. В итоге систем сборки как грязи, на любой вкус, что особенно доставляет, когда в одном проекте нужно объединить библиотеки, использующие разные системы.

    Понятное дело, что стандарт C++ — он совершенно не про то, и в стандарте не будет прописываться какая-то система сборки. Но хотя бы эта проблема затрагивается в кулуарах?


    1. 0xd34df00d
      22.11.2017 19:33

      В итоге систем сборки как грязи, на любой вкус, что особенно доставляет, когда в одном проекте нужно объединить библиотеки, использующие разные системы.

      Это как? Вы их прямо в дерево проекта добавляете и дёргаете их сборку из вашего мейкфайла/CMakeLists.txt/.jam?


      1. eao197
        22.11.2017 19:39

        Вы их прямо в дерево проекта добавляете и дёргаете их сборку из вашего мейкфайла/CMakeLists.txt/.jam?
        А как надо? Чтобы просто, кроссплатформенно, повторяемо?


        1. 0xd34df00d
          22.11.2017 20:04

          просто

          Я в своём CMakeLists.txt пишу find_package(meh), проще некуда.

          кроссплатформенно

          Положиться на пакетные менеджеры в соответствующих ОС/дистрах. Если какого-то пакета нет — добавить в интересующие вас (их не так много, в конце концов). От этого выиграете и вы, и всё сообщество.

          повторяемо

          Для каких целей? Если для ваших внутренних билдов — берёте условную убунту 16.04 LTS и радуетесь жизни в ближайшем будущем.

          Собственно, а иначе как? Какие-нибудь Qt будете втягивать? А libstdc++, от которых оно будет зависеть?
          С поддержкой программы, которая зависела всего-то от буста, но пыталась поставляться в виде одного бинарника под все возможные дистрибутивы линукса, я в своё время уже наелся, спасибо.


          1. eao197
            22.11.2017 20:11

            У вас какие-то странные представления о кроссплатформенности. Ну и да, не весь мир пользуется CMake. И не желает, что характерно.


            1. 0xd34df00d
              22.11.2017 20:17

              У вас какие-то странные представления о кроссплатформенности.

              Код не нужно переписывать под другую платформу, платформозависимые вещи выделены в отдельные слои, абстрагированы и протекают минимально, и так далее.

              Ну и да, не весь мир пользуется CMake. И не желает, что характерно.

              Я сам бы с радостью пользовался чем-то более приятным, но, увы, в общем случае лучше ничего нет. Или я подотстал от жизни?


            1. khim
              22.11.2017 20:23

              Ну и да, не весь мир пользуется CMake.
              А почему, собственно?
              И не желает, что характерно.
              Ах, вон оно чё, Михалыч. Ну дык а почему весь мир вдруг возжелает пользоваться новыми тулзами, которые комитет разработает?

              Думаете перейдут потому, что это стандарт? Тогда об этом смысла нет говорить без работающих модулей. Ибо переход на C++11 до сих пор не завершен — а ему, как бы, уже довольно много лет. То есть даже в самом оптимистичном случае распространение эта система получит уже в эпоху, когда C++'никам будет что ответить на вопрос: «почем в Tubro Pascal'е модули появились 30 лет назад, а в C++ их нет до сих пор». Без модулей в любой системе будет очень много времени и сил уходитm на обслуживание костылей, их заменяющих, а если скоро — системы управления зависимостями не будет, тогда зачем в ней всё это?


              1. 0xd34df00d
                22.11.2017 20:52

                А почему, собственно?

                Синтаксис наркоманский. Особенно строки сравнить, цикл сделать или что-нибудь такое.


    1. antoshkka Автор
      22.11.2017 19:39
      +1

      Была создана подгруппа Tooling (SG Tooling) в Альбукерке. Возможно что через пол годика можно будет посылать предложения по унификации систем сборок, пакетным менеджерам и прочему.


      1. eao197
        22.11.2017 19:41

        От оно чё, Михалыч… :) Ну будем посмотреть. Сам факт движения радует.


      1. ZaMaZaN4iK
        23.11.2017 03:21

        А как же позиция комитета, что «Тулзы не имеют никакого отношения к самому языку, почему мы ими должны заниматься»?


        1. eao197
          23.11.2017 08:49

          Думаю, что время и опыт «молодых» языков, вроде Rust-а и Go, показывает, что «тулзы не имеют отношения...» несколько устарело.


          1. ZaMaZaN4iK
            23.11.2017 14:43

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


            1. eao197
              23.11.2017 14:49

              Да, было такое мнение. Вопрос потому и возник, чтобы узнать, а не поменялось ли оно со временем.

              Ибо складывается ощущение, что C++-комьюнити само выбирает тот же CMake и ничего хорошего в этом нет :(

              Плюс есть такой фактор, что когда люди говорят про модули, которые ожидаются в C++, то у многих складывается ощущение, что с пришествием модулей наступит такое же благоденствие, как в каких-нибудь языках с поддержкой модулей, вроде D или Rust-а, где сам компилятор может разобраться в каком порядке что компилировать. С большой долей вероятности в C++ это будет не так. Если только коммитет на озадачиться тем, чтобы у языка была своя де-юре стандартная система сборки.


              1. ZaMaZaN4iK
                23.11.2017 23:42

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


                1. eao197
                  24.11.2017 08:41

                  Переносить тонны кода с C++98 на C++11/14/17 тоже не все торопятся. Это же не означает, что не нужно развивать C++, выпускать C++17 и разрабатывать C++20.

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

                  Тоже самое и системами сборки. Вот становится CMake де-факто стандартом и те проекты, которые развиваются, волей-неволей, но вынуждены либо переходить на CMake, либо добавлять какую-то поддержку для него (например, FindFoo.cmake-файлы).


  1. dev96
    22.11.2017 19:40

    P0275R2. Очень нужная вещь. Спасибо!)


  1. Ritorno
    22.11.2017 19:41

    std::is_pod и std::is_pod_v помечены как deprecated.
    Можно поподробнее?


    1. antoshkka Автор
      22.11.2017 19:48

      Помечены как deprecated, чтобы мотивировать людей использовать is_standard_layout и is_trivally_copyable.


      1. Ritorno
        22.11.2017 23:33
        -1

        То есть мотивировать людей писать локальную функцию?

        bool is_pod()
        {
          return is_standard_layout<T>::value && is_trivally_copyable<T>::value;
        }

        Какая-то сомнительная мотивация, хотя в type_traits это не единственная странность, взять к примеру наличие is_member_function_pointer, но отсутствие is_function_pointer.


        1. khim
          22.11.2017 23:43

          То есть мотивировать людей писать локальную функцию?
          А зачем вам эта функция? Если вы хотите засунуть это в realloc, то вам нужно is_trivally_copyable, если вам нужно с C общаться — вам нужен is_standard_layout, а вот случаи, когда нужно и то и другое — крайне редки (да собственно уже и is_trivally_copyable мало когда нужен, а уж чтобы был нужен POD и именно POD — я ни разу не встречал, хотя чисто теоретически такое можно придумать, но… не встречал).

          Взять к примеру наличие is_member_function_pointer, но отсутствие is_function_pointer.
          Та же самая ситуация: в 99% случаев вместо гипотетического is_function_pointer — нужно использовать is_invocable. А если очень нужно (зачем?) — то можно, наверное, и самому такое изготовить…


          1. Ritorno
            23.11.2017 21:18

            Мне запись is_pod кажется гораздо более очевидной, чем is_standard_layout, как и само определение «plain-old-data» проще осознать, чем «standard layout». Кроме того, раз уж добавили, то зачем убирать? Одно дело делать deprecated auto_ptr, вместо которого добавили несколько новых, а другое дело убирать что-то из type_traits, который просто предоставляет удобные штуки.

            Для is_invocable нужен список аргументов, и добавили его только в С++17, а не в С++11 как остальные две функции. Вопрос «зачем» здесь вообще не актуален, если есть библиотека для поддержки информации о типах, то там должно быть все, что с этим связано. С таким же успехом можно спросить «Зачем нужна is_arithmetic, если это всего лишь is_integral && is_floating_point?».


            1. khim
              23.11.2017 22:28

              С таким же успехом можно спросить «Зачем нужна is_arithmetic, если это всего лишь is_integral && is_floating_point?».
              Можно. И можно получить разумный ответ: есть вещи в стандарте, которые разрешены только для арифметических типов и запрещены — для всех остальных. А вот для POD — таких мест нет.

              Мне запись is_pod кажется гораздо более очевидной, чем is_standard_layout, как и само определение «plain-old-data» проще осознать, чем «standard layout».
              И именно поэтому сотни и тысячи програмистов используют is_pod там, где нужен is_standard_layout.

              Рассмотрим простой пример. Вот такой тип:
              struct Test {
                  int x = 0;
                  int y = 0;
                  int z = 0;
              };
              Ну надоела мне вечная возня с неинициализированными данными. Могу я его передать в C? Да, разумеется — это standard layout класс. Могу я использовать его с вашей библиотекой? Да господь с вами: вам же is_pod писать удобнее, а что кто-то там безопасности и предсказуемости хочет — так это его проблемы.

              Нафиг-нафиг-нафиг. Если что-то слишком легко использовать неправильно — то лучше это что-то из языка и/или библиотеки удалить. auto_ptr и is_pod — как раз такие вещи. Вы, собственно, так и не ответили на вопрос: где вы is_pod применяете и почему вам is_standard_layout не подходит. А без этого дальнейшие рассуждения как бы бессмысленны.


              1. Ritorno
                23.11.2017 23:20

                Да, похоже я использовал is_pod там, где достаточно is_trivially_copyable, но зато теперь стало понятно, зачем его хотят убрать.


                1. khim
                  23.11.2017 23:53

                  Об чём и речь. С появлением constexpr выражений (включая конструкторы и деструкторы!), default member initializers и прочего оказалось что слишком часто использование is_pod «не по делу» мешает писать красивый и удобный код.

                  Да, можно выкрутится, скажем сделать POD-класс предком того класса, с которым вы, в большинстве случаев, работаете, но это всё — костыли, которые грозят слезьми при малейшей ошибке. Гораздо лучше — использовать ровно то свойство, которое вам нужно. В C++17 POD'ы упоминаются буквально в паре мест — и, есть подозрение, что в C++ не будут упоминаться вообще нигде. Тем самым понятие потеряет всякий смысл с точки зрения языка.

                  P.S. Кстати класс из моего примера и is_standard_layout и is_trivially_copyable. Он не POD — потому что он не is_trivially_default_constructible — что тоже бывает нужно (например только такие типы вы можете считать «готовыми к употреблению с помощью reinterpret_castа поверх абстрактного куска памяти, выделенного mallocом) — но очень редко.


  1. gonzazoid
    22.11.2017 20:14

    Я понимаю что тут серьезные пацаны собрались, сами себе в зеркало не улыбаются, и все же — где фотки Los Pollos Hermanos, где Octopus Car Wash, где все это? Чего ездили, спрашивается? )


    1. Miraage
      22.11.2017 23:00

      Jesse, it's time to cook.


  1. dimka11
    22.11.2017 20:27

    Где бы это все попробовать?!


  1. Biga
    22.11.2017 21:40
    +1

    А в сторону reflection есть какие-нибудь подвижки?


    1. Error1024
      23.11.2017 11:54

      Не дождемся, графика в станадрте очевидно важнее!


      1. ZaMaZaN4iK
        23.11.2017 23:42

        Про графику ведутся только начальные разговоры. Так что не стоит беспокоиться, что Комитет ерундой занимается.


        1. Error1024
          24.11.2017 03:17

          Зато про reflection не введутся никакие почти, а первое нужно, и это должно быть частью языка. Графика же — не очень важная часть стандартной библиотеки.

          Я вот сижу на Delphi, как не посмотрю в сторону C++, нет почти подвижек, модули все только обещают, о рефлексии разговора толком нет, как вообще можно жить без рефлексии? Про строки которых 100500 у каждой либы и все не совместимы, я молчу(ок так исторически вышло).
          Зато графика, комплексные числа — в стандарте — ага, спасибо.


          1. khim
            24.11.2017 03:28

            о рефлексии разговора толком нет, как вообще можно жить без рефлексии?
            А чего именно вы хотите от рефлексии? А то как-то я спокойно без неё живу с type_traits… чего я такого важного теряю?

            P.S. Сразу предупреждаю, что инспекторы объектов я не пишу, но пользую — они отлично работают с DWARF'ом и поддержки в стандерте, как бы, не особо и требуют… всё равно для них требуется куча вещей, которых в стандарте нет… интересует куда и какую рефлексию аж такую, что без неё «жить нельзя» хотите приспособить… После получения реальных примеров уже можно будет и о расширении языка говорить…


            1. Error1024
              24.11.2017 03:32

              Какие реальные примеры нужны? — реальнее того что Qt работает исключительно чрез эмуляцию Reflection. Хочешь рефлексию — прикручивай костыли, сейчас, когда почти все языки поддерживают эту базовую функцию — даже не смешно говорить о необходимости. В любом случае это во много раз нужнее ограниченой графической либы.


              1. khim
                24.11.2017 03:59

                реальнее того что Qt работает исключительно чрез эмуляцию Reflection.
                Gtkmm работает без «эмуляции Reflection», Aura работает без «эмуляции Reflection», да и старый добрый WTL как-то без этого обходится.

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

                То, что Qt'шники хотят делать в рантайм вещи, которые на C++ сделать можно только в compile-time не значит что нужно прям всё бросать и превращать C++ в Java: есть сотни проектов и тысячи библиотек, которые без этого как-то живут. А для тех, кто хочет Java, вы не поверите, есть Java.

                Так что вопрос остаётся в силе: какую-такую рефлексию без которой «жить нельзя» вам нужно — и для решения какой бизнес-задачи вы хотите её приспособить? А также — и это очень важно — сколько будет «стоить» ваша рефлексия если вы её не будете использовать?

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

                То, что в C++ вообще есть RTTI, как мне кажется, есть ошибка (это одна из немногих фич, которая чего-то ощутимого стоит, когда ею не пользуются — недаром в большинстве компиляторов есть флаг -fno-rtti или что-нибудь подобное — а ведь «selling point» C++ состоит как раз в том, что ты не платишь за то, что не используешь), не стоит её усугублять.


                1. 0xd34df00d
                  24.11.2017 07:24

                  У кутешников до поры до времени была необходимость поддерживать сильно унылые компиляторы, поэтому всякие сигналы-слоты, которые до Qt 5 чаще всего использовали рефлексию, иначе не сделаешь. Да и даже в Qt 5 moc всё ещё генерирует немного кода для сигналов, и я не готов сходу сказать, что всё, что он делает, можно сходу переложить на компилятор.

                  Плюс, есть ещё всякие Q_INVOKABLE и Q_PROPERTY, которые торчат наружу в QML и прочие скриптовые вещи. В Gtkmm/WTL есть аналог QML?


                  1. khim
                    24.11.2017 14:20

                    Плюс, есть ещё всякие Q_INVOKABLE и Q_PROPERTY, которые торчат наружу в QML и прочие скриптовые вещи.
                    Они, к сожалению, просто «торчат наружу», а не «торчат наружу в QML». У вас нет никакой возможности узнать — используются они или нет.

                    С точки зрения языка это — просто некоторое описание данных для внешнего потребителя.

                    В Gtkmm/WTL есть аналог QML?
                    Нет, разумеется. Это будет противоречить самому принципу: программа должна быть доступна компилятору C++.

                    Как выдать данные дня «внешних потребителей» — над этим сейчас очень серьёзно работают. Но поскольку тут уже «играют» не только потребности C++-программистов, то очень тяжело понять, прежде всего — что, на самом-то деле нужно и что, без существенных изменений языка, возможно.

                    Когда мне в качестве примера говорят: а возьми, мил-человек, 50MB+ исходничков и перелопать из начала в конец и из конца в начало — а потом уж разговоры разговаривай… это неконструктивно. Вот это -уже конструктивнее. И SG7, разумеется, этот блог-пост читал…


                    1. 0xd34df00d
                      24.11.2017 20:50

                      Они, к сожалению, просто «торчат наружу», а не «торчат наружу в QML». У вас нет никакой возможности узнать — используются они или нет.

                      Я не вижу здесь каких-то особых проблем. Зачем мне об этом узнавать? Да и когда, в рантайме или в компилтайме? Если в рантайме, то это прикручивается, если в компилтайме, то для динамических вещей вроде QML или Python-скриптов это не особо возможно.

                      С точки зрения языка это — просто некоторое описание данных для внешнего потребителя.

                      Так и должно быть.

                      Только я бы голосовал за компил-тайм-рефлексию. Рантайм-рефлексия через неё выражается, а в обратную сторону оно не работает.

                      Нет, разумеется. Это будет противоречить самому принципу: программа должна быть доступна компилятору C++.

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

                      Но поскольку тут уже «играют» не только потребности C++-программистов

                      Эм, а чьи ещё? Мы ж о С++ говорим.


                      1. khim
                        24.11.2017 21:11
                        +1

                        Зачем мне об этом узнавать?
                        Затем что иначе нарушается базовый принцип C++: платите только за то, что используете.

                        Что значит, что подход, принятый в Java или Qt для C++, в общем, недопустим: нужны не метаклассы как таковые, а инструменты для их создания.

                        Если в рантайме, то это прикручивается, если в компилтайме, то для динамических вещей вроде QML или Python-скриптов это не особо возможно.
                        Что, собственно, и обозначает, что требуется помощь со стороны программиста — только он может сказать какое, когда и в каких количествах знание нужно экспортировать из C++ программы.

                        Только я бы голосовал за компил-тайм-рефлексию. Рантайм-рефлексия через неё выражается, а в обратную сторону оно не работает.
                        Это само собой — но это сразу же ставит кучу вопросов, которые достаточно сложно решать. Очень мало языков имеют компайл-тайм рефлексию не имея рантайм рефлексии. C++ здесь, во многом, первопроходец.

                        Безотносительно принципов, на QML всякие свистелки-перделки очень кратко и ёмко выражаются, и для некоторых сортов интерфейсов и задач это самое оно.
                        Возможно. Но на C++ — свет клином не сошёлся и, возможно, для решения каких-то задач стоит использовать другой язык. Я вот не уверен, что «свистелки-перделки» использующие в 10-100 раз больше ресурсов, чем, на самом деле, нужно — это вообще то, что нужно делать на C++.

                        Эм, а чьи ещё? Мы ж о С++ говорим.
                        Нет. Когда мы начинаем рассуждать о DBus, QML и прочем — то это значит, что у нас появляются какие-то жёстко заданные требования «извне», которые в языке C++ не определяются.

                        Такие вещи в C++ есть (начиная с extern "C", ага), но говорить о них всегда сложнее, так как эсперты по этим «внешним» вещам считают очевидным, что все понимают — что им нужно, что, как бы, ни разу не так для людей, которые соответствующую технологию не используют.


                        1. 0xd34df00d
                          24.11.2017 21:23
                          +1

                          Затем что иначе нарушается базовый принцип C++: платите только за то, что используете.

                          Не добавляю маркер Q_OBJECT — не плачу. Добавил — подразумеваю возможность использования.

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

                          Конечно. О рантайм-рефлексии для всего и вся по умолчанию никто в здравом уме и не говорит.

                          Очень мало языков имеют компайл-тайм рефлексию не имея рантайм рефлексии.

                          Ну взять тот же TH и черпать вдохновение оттуда.

                          Но на C++ — свет клином не сошёлся и, возможно, для решения каких-то задач стоит использовать другой язык. Я вот не уверен, что «свистелки-перделки» использующие в 10-100 раз больше ресурсов, чем, на самом деле, нужно — это вообще то, что нужно делать на C++.

                          Под этим QML может лежать тяжёлая бизнес-логика на плюсах, которую на этих плюсах имеет смысл делать.

                          А сколько оно там ресурсов жрёт — ну можно и с CLI сравнить, в конце концов.

                          Нет. Когда мы начинаем рассуждать о DBus, QML и прочем — то это значит, что у нас появляются какие-то жёстко заданные требования «извне», которые в языке C++ не определяются.

                          А, в этом смысле.

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


                          1. khim
                            24.11.2017 22:42

                            Ну, эти юзкейсы должны быть чем-то вроде граничных условий, позволяющих проверить, является ли данное предложение о рефлексии разумным, позволяет ли оно выразить те юкзейсы, или нет.
                            Ну дык об этом и речь! Отсюда, собственно, и нужно «танцевать». А не с заявлений: нужна именно внтуриязыковая по типу в C# или Java. Если вам нужен C# или Java, то, чёрт побери, кто вам запрещает использовать C# или Java? Они проде есть и умирать (к сожалению или к счастью — не знаю) пока не собираются…


                    1. Antervis
                      25.11.2017 08:24

                      Вот это -уже конструктивнее. И SG7, разумеется, этот блог-пост читал…

                      Предложение Герба Саттера по метаклассам всё-таки попроще будет


                1. Tantrido
                  24.11.2017 16:34

                  Это уже разговор ни о чём пошёл. Если бы в C++ была рефлексия — язык рванул бы по возможностям на уровень C# и Java, но значительно превосходил бы их в скорости и используемой памяти. Те же GUI, которые на Qt летают, на C#, Java страшно тормозят: IDE, приложения с контролами (таблицы, комбобоксы), в которых много элементов и т.д. и т.п.

                  Хорошо, что благодаря Qt эти вопросы решаются и сильно расширяют возможности C++.


                  1. DistortNeo
                    24.11.2017 16:47

                    Тормознутость GUI связана не с языком, а с GUI фреймворками и использующими их криворукими программистами.

                    IDE Visual Studio написана на .NET (WPF), и она совершенно не тормозит.
                    IDE Idea, Rider написаны на Java, и они тоже не тормозят.


                    1. Tantrido
                      24.11.2017 16:55

                      Это были сводки из параллельной реальности?

                      1) Напиши таблицу в C++/Qt Excel на тысячи строк и пару десятков столбцов — она не будет тормозить. И в C#/Java хотя бы пару сотен строк (лаги видные невооружённым взглядом) и сравни.
                      2) IDE Visual Studio — посмеялся. Сравни с 2008 студией, когда там WPF ещё не было
                      3) IDE Idea — пользуюсь каждый день, но сравнивать с реактивным Qt Creator смешно особенно запуск (в идее — около минуты, креатор — несколько секунд), загрузку проекта, скроллинг и навигацию.


                      1. DistortNeo
                        24.11.2017 17:07

                        1) И на C# не будет тормозить, если не использовать какой-нибудь DataGrid, обвешанный рефлексией, а использовать более низкоуровневые примитивы. Да, чтобы работало быстро, придётся ручками писать код.

                        2) Сейчас подходит к концу 2017 год.

                        3) Ну так и пользуйтесь Qt Creator-ом. Всё дело в функционале же.


                        1. Tantrido
                          24.11.2017 17:10

                          Да, чтобы работало быстро, придётся ручками писать код.
                          … на C++

                          Ну так и пользуйтесь Qt Creator-ом. Всё дело в функционале же.
                          Дело не в креаторе или IDEA — пользуемся тем, что нужно для задачи. А в том, что с рефлексией уровень задач решаемых C++ значительно бы вырос.


                          1. khim
                            24.11.2017 19:41

                            А в том, что с рефлексией уровень задач решаемых C++ значительно бы вырос.
                            Совершенно необязательно. На примера Java я вижу, что рефлексию, как правило, используют для того, чтобы сделать код «гибчее» и… медленнее и прожорливее!

                            Я не уверен, что это прям то, что так уж нужно С++. Но да, в определённых случаях во всём этом есть смысл.


                          1. DistortNeo
                            24.11.2017 21:48

                            … на C++

                            Это не важно, даже при использовании C# основное процессорное время будет затрачено в user32.dll и gdi32.dll.
                            Хотите, чтобы я привёл пример?


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


                            1. Tantrido
                              25.11.2017 00:15

                              Это не важно, даже при использовании C# основное процессорное время будет затрачено в user32.dll и gdi32.dll.
                              Почему Qt не затрачивает это процессорное время? Обычная программа на C#/Java работает раза в 2 медленнее, а GUI на порядок медленнее, чем C++/Qt.


                              1. DistortNeo
                                25.11.2017 15:37

                                Обычная программа на C#/Java работает раза в 2 медленнее

                                Да, работает медленее. И что? Просто не пишите UI, требующий большого количества вычислений.


                                а GUI на порядок медленнее, чем C++/Qt.

                                А QtSharp?


                                И вообще, как GUI может работать медленнее, если он просто сводится в вызову системных функций?


                                1. khim
                                  25.11.2017 16:09

                                  «GUI работает медленнее» — это такой эвфемизм вместо «реакция на событие не происходит за ожидаемые 16 миллисекунд».

                                  И да, здесь многоуровневые слои рефлексии и фабрики-фабрик-фабрик ни разу не помогают.


                                1. Antervis
                                  25.11.2017 16:19

                                  Да, работает медленее. И что? Просто не пишите UI, требующий большого количества вычислений.

                                  Тут вопрос стоит так: «справляется или не справляется GUI-поток?». Справляется? — всё хорошо. Не справляется? — плохая программа, тормозит и виснет. А реальная разница в быстродействии может быть и в не вдвое, а процентов на 20
                                  И вообще, как GUI может работать медленнее, если он просто сводится в вызову системных функций?

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

                                  Итоговая программа всё равно должна удовлетворять требованиям, в т.ч. и по отзывчивости/быстродействию. Не сказал бы, что на с++/Qt программы пишутся прям намного дольше, чем на шарпике. Для некоторых приложений возможно даже, что и быстрее, т.к. меньше времени уйдет на оптимизацию бизнес-логики.


                    1. khim
                      24.11.2017 17:41

                      IDE Visual Studio написана на .NET (WPF), и она совершенно не тормозит.
                      IDE Idea, Rider написаны на Java, и они тоже не тормозят.
                      Ага. Щаз. Запустите из на Atrom'е на 1GHz и сравините с Visual Studio 6.0 (последняя, не испорченная C#).

                      И современная Visual Studio и Idea и Rider — тормозят безбожно. Конечно сделать их тормозами не было основной задачей и за то, что системные ресурсы и потребная мощность процессора возросли на два порядка мы таки кое-что получаем, но… контрпримерами они не являются ни разу, увы.


                    1. 0xd34df00d
                      24.11.2017 20:51

                      Сделайте s/Idea/CLion/ и сравните результат с KDevelop. Я тут KDevelop ради интереса открыл после где-то года с CLion — божечки, как я отвык от нетормозящего набора текста!

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


                      1. khim
                        24.11.2017 21:14

                        модель кода и всякие рефакторинги-интеллисенсы в CLion лучше, но это не повод тормозить
                        Де нет — в общем-то повод (пока никто не сделал быстрого интерфейса с хорошим интеллисенсом, так что ясно, что это непросто), но… это хороший тест: если человек заявляет, что CLion, Idea, MSVC, или, не дай бог, Eclipse «не тормозят» — это значит либо, что у него плохое зрение, либо что у него очень, очень дорогой и быстрый компьютер — а часто и то и другое одновременно.


                        1. 0xd34df00d
                          24.11.2017 21:30

                          Де нет — в общем-то повод

                          Ну как же, ну есть же многопоточность и все дела.

                          Просто IDE для плюсов самих по себе не так уж много, чтобы была какая-то разумная статистика.

                          либо что у него очень, очень дорогой и быстрый компьютер — а часто и то и другое одновременно

                          У меня дома i7 3930k с 64 гигами оперативки. Только этому CLion хоть тредриппер купи — он всё равно при подвисании только одно ядро жрёт.


                        1. DistortNeo
                          24.11.2017 21:53

                          Вы правы. Не вижу никакого смысла использовать Atom для
                          разработки. Ведь компьютер — это основной инструмент, а на инструментах экономить нельзя.


                          Ну и важный момент — мои проекты не очень большие (~500 файлов, 3М текста), а студию я использую голую, т.к. с плагинами (Resharper, VAssist) она действительно тормозит.


                  1. khim
                    24.11.2017 16:48

                    Хорошо, что благодаря Qt эти вопросы решаются и сильно расширяют возможности C++.
                    Так они «решаются» или «если бы в C++ была рефлексия — язык рванул бы»?

                    Вы уж выберите что-то одно, а?

                    Это уже разговор ни о чём пошёл.
                    Я понимаю, что для верующих обсуждать вопрос их веры бессмысленно, но вроде как пока что «школы адептов рефлексии» не наблюдается, так что вопросы нужно обсуждать по-существу, а не в духе «примите нашу веру — и будет вам ЩАСТЯ».


                    1. Tantrido
                      24.11.2017 16:57

                      Qt — не стандарт, не все хотят дополнительные библиотеки тянуть в свой проект только из-за рефлексии.


                      1. khim
                        24.11.2017 17:46

                        А тогда непонятно, чем вам рефлексия в языке поможет. «Внутриязыковая» рефлексия в C++ уже и так достаточно развита. То, что нужно — это «внеязыковая» рефлексия позволяющая как-то общаться с библиотеками и скриптами не написанными на C++.

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

                        Вы уж определитесь — вам шашечки или ехать.


                        1. Tantrido
                          24.11.2017 18:03

                          А тогда непонятно, чем вам рефлексия в языке поможет. «Внутриязыковая» рефлексия в C++ уже и так достаточно развита.
                          Это какая, например?

                          То, что нужно — это «внеязыковая» рефлексия позволяющая как-то общаться с библиотеками и скриптами не написанными на C++.
                          Ничего подобного не требовалось. Нужна именно внтуриязыковая по типу в C# или Java.


                          1. khim
                            24.11.2017 19:44

                            Это какая, например?
                            Magic Get, к примеру. Коего вполне достаточно для RPC, например. Или сериализации.


                          1. DistortNeo
                            24.11.2017 21:55

                            Нужна именно внтуриязыковая по типу в C# или Java.

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


                            1. khim
                              24.11.2017 22:39

                              Не «бессмысленно», а «не нужно». Это будет другой язык с другой областью применения. Как какой-нибудь C++/CLI.


                      1. 0xd34df00d
                        24.11.2017 20:52

                        Тем более, что в Qt рефлексия очень ограничена и вообще рантайм.


            1. 0xd34df00d
              24.11.2017 07:22

              А чего именно вы хотите от рефлексии? А то как-то я спокойно без неё живу с type_traits… чего я такого важного теряю?

              Смотря что вы делаете.

              Я бы хотел, ну… Слышали про Template Haskell что-нибудь? Но это так, недостижимые грёзы. В мире С++ я бы хотел написать один раз один метакласс, который потом мне сгенерит DBus-обёртки для моего типа. Или будет проксировать вызовы методов через какой-нибудь [другой] RPC-механизм. Или сгенерирует методы для сериализации-десериализации. Или для работы с представлением типа в БД.

              Конкретно последнее я, конечно, могу и сам написать, но придётся делать всякие некрасивые BOOST_FUSION_ADAPT_STRUCT, да и реализация выглядит совсем не как образец читабельности. Надо бы там, кстати, что-нибудь придумать, чтобы селекты писать как Select(fieldName == "meh") вместо Select(_0 == "meh"), но кроме макросни либо нечитаемых указателей на члены ничего в голову не лезет.


              1. khim
                24.11.2017 14:30

                Слышали про Template Haskell что-нибудь?
                Слышал, слышал. Про то, как вызывать его из Java или C++ библиотеки — не слышал.

                В мире С++ я бы хотел написать один раз один метакласс, который потом мне сгенерит DBus-обёртки для моего типа.
                Ну то есть опять — что-то для внешнего потребителя. Который не существует на этапе компиляции программы. Тут сразу встаёт задача классификации этих потребителей и их «хотелок». Так как они «живут» вне C++ кода, то про них и их «желания»/«ограничения» мы знаем очень мало. И пока не будем знать достаточно — хорошего решения не придумаем.

                Или будет проксировать вызовы методов через какой-нибудь [другой] RPC-механизм.
                Опять-таки: чего вы от него хотите.

                Или сгенерирует методы для сериализации-десериализации.
                Magic Get делает это в рамках C++14.

                Или для работы с представлением типа в БД.
                А тут — снова возникает вопрос: что конкретно и зачем.

                То есть так-то понятно, что рефлексия — это хорошо… но вот что именно нужно и насколько оно востребовано… дьявол, как обычно, в деталях. C++ — всё-таки компилируемый язык… Мне очень нравится Beautiful Soup — но я понимаю что подобные трюки в C++ не сработают если мы захотим в «жёсткую структуру» всё загнать: на этапе компиляции мы ж не знаем какие теги возможны и какие в них могут быть субтеги! А если всё делать гибко поверх std::any — ну так там и рефлексия сразу в таком дереве будет!


                1. 0xd34df00d
                  24.11.2017 21:03

                  Слышал, слышал. Про то, как вызывать его из Java или C++ библиотеки — не слышал.

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

                  И ни для чего из этого не нужно прямой поддержки в ядре языка, всё это библиотечный код, в ядре языка достаточно просто уметь управляться с AST.

                  Ну то есть опять — что-то для внешнего потребителя.

                  Почему? Для меня любимого. Просто написать метакласс для DBus один раз приятнее и веселее, чем методично кодогенерировать или писать обёртки руками. И я даже знаю это всё на этапе компиляции.

                  Опять-таки: чего вы от него хотите.

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

                  А тут — снова возникает вопрос: что конкретно и зачем.

                  Не писать тонны бойлерплейта руками. Хочу по
                  struct Person
                  {
                      PKey<int> m_id;
                      int m_age;
                      std::string m_name;
                  };
                  
                  struct Payment
                  {
                      PKey<int> m_id;
                      References<&Person::m_id> m_person;
                      double m_amount;
                  };
                  

                  сгенерить две таблички и все функции для вставки-удаления-обновления этих записей, а также селекта по всем возможным полям и ограничениям, типа select(&Payment::m_amount >= 1000 && &Payment::m_person == &Person::m_id && &Person::m_age < 25). Вышеупомянутая хренотень делает почти это, только вместо &Payment::m_amount надо писать _2 (обращения по индексу), и кросстабличные запросы я пока вроде не запилил.

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

                  Это как сравнивать SFINAE-костыли и полноценные концепты.


                  1. khim
                    24.11.2017 21:20

                    И ни для чего из этого не нужно прямой поддержки в ядре языка, всё это библиотечный код, в ядре языка достаточно просто уметь управляться с AST.
                    Этим путём идёт rust… посмотрим что из этого выйдет.

                    Конечно, вы правы — она это уже делает, но есть чувство, что через правильную рефлексию оно всё будет выглядеть куда лучше.
                    А в этом, собственно, и проблема: поскольку через костыли это делается уже сейчас — то никому неинтересно добавлять «какую-нибудь» рефлексию. «Какая-нибудь» уже есть (и не одна, да).

                    Это как сравнивать SFINAE-костыли и полноценные концепты.
                    Не обязательно SFINAE. DWARF — это тоже рефлексия и тоже стандарт, хотя и не ISO C++.

                    В том-то и дело, что уже много чего есть и вопли «адептов рефлексии» — это «пена», на которую не стоит обращать много внимания.

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


                    1. 0xd34df00d
                      24.11.2017 21:28

                      Этим путём идёт rust… посмотрим что из этого выйдет.

                      В каком-то смысле да, это любопытный эксперимент даже при наличии TH. Хотя бы потому, что синтаксис раста куда богаче синтаксиса хаскеля, поэтому TH на хаскеле выглядит сильно проще.

                      никому неинтересно добавлять «какую-нибудь» рефлексию. «Какая-нибудь» уже есть (и не одна, да).

                      Поэтому я и говорю о правильной.

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

                      Конечно. Надо просто не забывать, что само оно не придумается, и надо думать. Ну или пинать чуваков из Яндекса, чтобы они пинали Комитет, чтобы он думал.


            1. Error1024
              24.11.2017 22:51

              Это на уровне — зачем вам полноценные строки в C?
              Я обожаю чистый C, и спокойно обхожусь без строк, но их отсутствие заставляет меня выбрать другой язык для некоторых задач, где отлично бы подошел C, были бы в нем строки.
              Также и тут, это сильно ограничивает возможности C++, хотя-бы отсутствием возможности сделать автоматическую сериализацию. И да, я видел несколько попыток сделать это макросами и набором костылей — это плохой способ, в котором разбирается только автор.


              1. khim
                24.11.2017 23:07

                И да, я видел несколько попыток сделать это макросами и набором костылей — это плохой способ, в котором разбирается только автор.
                Кто вам сказал, что сериализация, которую напишут поверх рефлексии будет лучше?

                Это тогда уж нужно добавлять библиотеку сериализации в стандарт — а это совсем-совсем другая история. Её, как бы, можно сделать уже сейчас через magic_get, но… не делают. Пользуют всякие протобуфы, Cap’n Proto или даже JSON'ы.


                1. Error1024
                  25.11.2017 16:19

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


                  1. khim
                    25.11.2017 18:20

                    Вы написали много слов, но не привели ни одного конкретного убедительного примера. Только общие слова в стиле «на дворе XXI век, а у нас рефлексии нету».

                    Хочется увидеть примеры, которые были бы осмысленны в рамках C++. «Эмуляция рефлексии» в Qt к подобным примерам отнесена быть не может: как уже верно заметили Qt был сделан именно так, потому что хотелось поддерживать «весьма унылые компиляторы». Другие современные библиотеки спокойно существуют без рефлексии.

                    Сериализация через рефлексию — это круто и здорово… только вот в Java, где вроде как рефлексия и есть и сериализация через неё есть RPC делают не через сериализацию поверх рефлексии, а через JSON, XML и многое другое. А рефлексию используют для того, чтобы сделать программы «гибчее»… и тормознее. А последнее — это уже совсем не C++-way.

                    Пока что единственный заслуживающий внимания пример — это генерация Dbus-биндингов. Тут — действительно рефлексия нужна и в том виде, в каком она есть недостаточна.

                    Все же остальные примеры — скорее о том, как с помощью рефлексии что-то сделать плохо (медленно, небезопасно и с затратой кучи памяти). Вряд ли желание кого-то что-то делать «быстро и плохо» — может являться причиной для добавления новой фичи в язык. Языков, на которых получить более быструю разработку за счёт качества получаемого продукта — достаточно много и без C++.


                    1. Error1024
                      25.11.2017 18:23

                      <сарказм>
                      Приведите хоть один убедительный пример зачем в C++ есть шаблоны?
                      Много проектов, которые генерируют код сторонними скриптами, есть 101 способ обойтись без шаблонов. Шаблоны лишь затрудняют чтение кода. Зачем они нужны не ясно.
                      </сарказм>


                      1. splav_asv
                        25.11.2017 18:48

                        Знаете, мне сейчас эта дискуссия напомнила дискуссии в сообществе Rust по поводу нужности типов высшего порядка. Много кто говорил, что нужно обязательно добавить HKT. Зачем — ну они позволяют решать много проблем, в Haskell и др. успешно применяются. Только в итоге ответом было: да, задачи есть, да, их можно решить HKT. В других языках это может хорошо работать и быть хорошим решением. Но Rust имеет свои особенности и напрямую HKT не ложатся на общую структуру языка. Но есть другой способ получить почти то же самое, который решает вроде бы все задачи, которые решает HKT и при этом хорошо интегрируется в язык.

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


                      1. khim
                        25.11.2017 21:19

                        <сарказм>
                        Приведите хоть один убедительный пример зачем в C++ есть шаблоны?
                        Много проектов, которые генерируют код сторонними скриптами, есть 101 способ обойтись без шаблонов. Шаблоны лишь затрудняют чтение кода. Зачем они нужны не ясно.
                        </сарказм>
                        Уберите теги "</сарказм>", пожалуйста.

                        Потому что ваши слова правильны и справедливы. Как же так: как я, фанат таких вещей, как Boost.Hana или любитель что-нибудь этакое сотворить через шаблоны могу так говорить?

                        А вот так. Шаблоны, в том виде, в котором они изначально были задуманы — практически никому не нужны. Я не могу вспомнить ни одного проекта, в котором я бы использовал basic_string, но не std::string, а всякие mapы — вполне могли бы существовать в виде Ada-стайл genericов.

                        А шаблоны… шаблоны — нет, не нужны. Что было нужно (и сейчас нужно!) — так это средства метапрограммирования. Однако их — в С++ не было. А шаблоны — были. И вот, когда Степанов придумал как с помощью шаблонов можно сделать плохое, кривое, но… всё-таки, работающее метапрограммирование — язык C++ стал чем-то большим.

                        Однако то, что метапрограммирование в нём — плохое и неудобное, а шаблоны по-прежнему не нужны — накладывает особый отпечаток на программистов на C++. Они плавают на перевёрнутом «вверх ногами» Боинге, а тот факт, что для этого нужно тщательно следить, чтобы ни через один иллюминатор не просочилась вода — считают достоинством и объясняют новичкам, что «так и надо».

                        Нет — так, не надо. Надо бы — корабль использовать. Но… корабля у нас нет, а вот этот самый Боинг с рядами гребцов — у нас есть. Но раз мы плаваем на Боинге, то и некоторые решения у нас оказываются… специфические. И вовсе не факт, что прикрутив на этот Боинг гребной винт мы получим облегчение: совершенно не факт, что эта конструкция будет лучше плавать — уж очень она отличается от той, для которой предлагаемый винт изначально предлагался…


                        1. eao197
                          25.11.2017 21:30

                          И вот, когда Степанов придумал как с помощью шаблонов можно сделать плохое, кривое, но… всё-таки, работающее метапрограммирование — язык C++ стал чем-то большим.
                          Это когда это Степанов придумал метапрограммирование на шаблонах? Степанов реализовал на шаблонах C++ свои идеи по обобщенному программированию, которые у него были еще с начала 1980-х. А метапрограммирование на шаблонах — это, как минимум, 1995-й год, когда STL уже был и его включали в первый стандарт C++.


                          1. khim
                            25.11.2017 21:58

                            Да, вы [почти] правы: как гласит wiki первая метапрограмма — это Erwin Unruh, 1994й, действительно к Степанову отношения не имеет.

                            Но остального — это не меняет: шаблоны в современном C++ используются почти исключительно «не по назначению», все связанные с ними проблемы (бинарники в 100500 магабайт и прочее) — имеют место быть, так что тот факт, что из-за мелкой случайности «история пошла совсем не туда» — отстаётся в силе.

                            Я думаю в альтернативном мире, где не было бы частичной специализации (то есть там, где шаблоны были бы дженериками), и где в C++ пришлось бы добавлять и нормальную рефлексию и нормальное метапрограммирование — всё было бы по-другому и, скорее всего, лучше и удобнее… но мы не живём в этом мире, увы… и попытки скрестить то, что есть с тем, что, как бы, хочется способны родить тааакого урода, что использовать его не захочется никому и ни для чего…


                            1. eao197
                              25.11.2017 22:02

                              шаблоны в современном C++ используются почти исключительно «не по назначению»
                              Не следует говорить за всех.


                        1. Antervis
                          25.11.2017 22:05

                          вы, как и большинство других, забываете, что с++ развивался эволюционно. Сначала люди вопили «надоел препроцессор! Сделайте параметризуемые типы». Voila. Потом люди заметили, что со скрежетом можно реализовать на шаблонах какую-то compile-time логику и стали этим пользоваться, вопя «неудобно, сделайте чтоб было лучше». В языке появились constexpr (if), variadic'и, SFINAE и пр. Снова не то: некоторые вещи пишутся очень уж многословно. Тут на выручку спешат концепты, но…

                          Людям то «виднее». Им подавай «как в ***», где *** — каждый второй ЯП. Им надо «чтобы просто вот такой код генерировался с набором параметров». Люди хотят еще один препроцессор…

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

                          Разве что с T&& в шаблонах реально бред вышел


                          1. DistortNeo
                            25.11.2017 23:05

                            И всё это можно было бы решить разработкой нового языка. Но проблема в том, что этот язык никто не будет использовать, потому что он не будет совместим с C++.

                            Если бы компилирование было двухэтапое: сначала в VM, затем в нативный код, то это было бы просто. Например, существует множество совметимых друг с другом языков, которые компилируют в MSIL или JVM.


                            1. Antervis
                              26.11.2017 00:24

                              и что теперь, каждую проблему каждого ЯП решать созданием нового ЯП? А он точно будет лучше? И окупится ли для программиста переход на этот новый язык вместо использования «старого доброго»?


  1. Handen
    22.11.2017 22:16
    +1

    Зашёл сюда посмотреть шутки про «Во все тяжкие»)


    1. gonzazoid
      23.11.2017 00:11

      better call Soul тоже ничего, мне даже больше понравился.


      1. Psychosynthesis
        23.11.2017 11:25

        Скоро новый сезон =)


  1. mezastel
    23.11.2017 00:50
    -1

    Я конечно прошу прощения, но вам не кажется что пример оператора spaceship, который показан в начале статьи, не имеет особого смысла? Когда и в каком сценарии вы будете сравнивать точки в трехмерной системе координат, сравнивая поочередно x, потом y, потом z? Это нонсенс! Оператор == реализован логично, это понятно. А вот < и > совершенно безумно. Вот если бы сравнение было по модулю sqrt(x*x+y*y+z*z) я бы еще понял.

    Формализация поведения оператора <=> вручную тоже получилась нечитабельной. Почему нельзя дать пользователю задать критерий сравнения как функцию, которая возвращает некий тип T, для которого однозначно реализованы операторы ==,<,>? Тогда можно было бы один раз посчитать модуль точки и использовать это значение во всех сравнениях.


    1. khim
      23.11.2017 01:04

      Когда и в каком сценарии вы будете сравнивать точки в трехмерной системе координат, сравнивая поочередно x, потом y, потом z?
      Когда захотите засунуть из в std::map, к примеру.

      Вот если бы сравнение было по модулю sqrt(x*x+y*y+z*z) я бы еще понял.
      А этот безумный вариант вы где хотите использовать?

      Почему нельзя дать пользователю задать критерий сравнения как функцию, которая возвращает некий тип T, для которого однозначно реализованы операторы ==,<,>?
      Это лишает затею всякого смысла. Дело в том что на многих процессорах можно достаточно дёшево посчитать <=> для чисел (и не только — см. strcmp) — а дальше из «элементарных» построений над числами можно уже построить что угодно.

      Но ясно же, что на практике всё это будет строиться в основном над строками — где как раз подобные построения уместны и разумны.

      P.S. Пример всё равно не очень удачен. Текущее положение дел как-то уж очень страшно описано. Что мешало написать не как на C++98, а как на C++11:
      bool operator==(p_ref a, p_ref b) {
          return std::tie(a.x, a.y, a.z) == std::tie(b.x, b.y, b.z);
      }
      
      bool operator< (p_ref a, p_ref b) {
          return std::tie(a.x, a.y, a.z) < std::tie(b.x, b.y, b.z);
      }


      1. antoshkka Автор
        23.11.2017 10:32

        Так пример же мотивирующий, так что «плохой» вариант должен быть по длиннее :)


      1. 0xd34df00d
        23.11.2017 19:48

        P.S. Пример всё равно не очень удачен. Текущее положение дел как-то уж очень страшно описано. Что мешало написать не как на C++98, а как на C++11:

        Так писать тоже, кстати, не надо, потому что довольно легко с одной из сторон указать, скажем, b вместо a, либо какой-нибудь член повторить два раза. Проще сделать метод, возвращающий тупл для текущего объекта, там пространство для ошибок меньше, и они заметнее.


    1. 0xd34df00d
      23.11.2017 19:47

      Почему нельзя дать пользователю задать критерий сравнения как функцию, которая возвращает некий тип T, для которого однозначно реализованы операторы ==,<,>?

      Ну напишите один раз в хедере где-нибудь шаблонный operator==/operator>/etc, включенный только для типов, имеющих метод as_tuple(), а в своих типах пишите
      auto as_tuple() const
      {
          return std::tie(field1, field2, field3);
      }
      


      А так — очень часто в операции сравнения не нужен физический смысл (чем лексикографическое сравнение векторов плохо, кстати?), а нужна всего лишь корректность и гарантия, скажем, полного порядка для возможности сортировки или запихивания в мапы. Тогда в плюсах пишется соответствующий оператор, сравнивающий всё подряд, это неудобно и лишняя писанина тогда как в хаскеле пишется всего лишь deriving(Eq, Ord).

      Ещё бы добавили автоматический вывод функций для хеширования, вообще было бы ништяк.


  1. luntik2012
    23.11.2017 09:47
    -1

    хорошо, что в си яндекс пока не умеет


  1. Stronix
    23.11.2017 10:16

    osyncstream

    Не знаток С++, однако есть же мьютексы, зачем городить очередную сущность?


    1. antoshkka Автор
      23.11.2017 10:28

      osyncstream работает без мьютексов под капотом. Так что он немного производительнее и намного лучше масштабируется.


  1. gdt
    23.11.2017 11:26

    starts_with и ends_with для строк

    Давно пора.


    1. ZaMaZaN4iK
      23.11.2017 14:24

      Было бы лучше, если бы это было как свободные функции =) Но нам этого ещё долго ждать. Следующий великий шаг — добавление std::trim в библиотеку :-)


  1. Tantrido
    23.11.2017 15:27

    Когда будет нормальная рефлексия?


    1. Error1024
      23.11.2017 15:46

      Похоже что никогда


    1. antoshkka Автор
      23.11.2017 15:59

      Не в C++20. Надеюсь что в C++23


      1. Tantrido
        23.11.2017 16:09

        Ложка дорога к обеду. Пока что Qt — наше всё в плане рефлексии! :)


      1. Error1024
        24.11.2017 03:19

        Боюсь самые лояльные адепты C++ плюнут на это все, за этот срок.


  1. Tantrido
    23.11.2017 15:28

    Атомарные умные указатели — это что?


  1. sena
    23.11.2017 16:28

    А что там с локализацией и юникодом? Где почитать, что уже есть и чего ещё нет?


    1. khim
      23.11.2017 17:31

      Дык эта. Как обсуждалось единороги — уже давно есть.

      Или вы о чём-то другом?


      1. sena
        23.11.2017 19:26
        +1

        Локализация — поддержка перевода текстовых строк на разные языки. То есть то, чем занимается, например, GNU gettext, а также всякие форматы дат и т.п.

        Поддержка юникода — классификация символов, поиск/замена, регулярки, конвертация из/в других кодировок. То есть то чем занимается ICU. Но не только — важна поддержка перекодировки для локальных имён файлов/каталогов, например. Или конвертация вывода в std::cout из юникода в локальную кодировку «на лету» и т.п.

        На сколько эти все работы завершены и что ещё не сделано?


        1. khim
          23.11.2017 22:41

          Это ещё хлеще, чем мертворождйнный высер P0267.

          Сейчас только что посмотрел на сборку Android'а: вся стандартная библиотека (C и C++ вместе) — порядка 2MB, в то время, как только ICU — это две библиотеки на 4MB плюс файл данных на 20MB.

          То есть вы хотите из-за того, что вам лично захотелось GUI изобразить увеличить стандартную библиотеку в десять с лишним раз? Губозакатывательные машинки продаются в соседнем отделе.

          Вот в виде отдельного опционального TS — пожалуйста, милости просим. А в стандарную библиотеку — ну никак. Извините.


          1. Antervis
            24.11.2017 11:35

            работу с локалями можно вынести в отдельную либу, поставляемую рядом со стандартной, по аналогии с atomic либой в gcc. Если она не нужна, то она просто не линкуется.


          1. sena
            24.11.2017 12:23

            Я правильно понял, что прогресса в этой области нет и комитет по стандартизации занимается… гм… другими полезными (на их взгляд) нововведениями?

            Сегодня, на секундочку, 2017 год и отсутствие такой, в сущности, базовой функциональности это какой-то позор…

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

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


            1. khim
              24.11.2017 13:40

              Для всяких встраиваемых недокомпьютеров (а телефоны к ним не относятся), как уже указал Antervis, вполне можно сделать либо обрезанную библиотеку, либо отдельный модуль.
              Ну и? Кто будет это делать? Кстати почему это «телефоны к ним не относятся»? ICU отсуствует в Android NDK — ровно по причине того, что её размеры слишком велики, а API имеющейся библиотеки нестабилен (то есть она не может быть частью системы).

              Да, там периодически происходят разные разговоры на тему выделения стабильной части, которую уже можно было бы включить в NDK… но пока — это всего лишь разговоры! А вы хотите сразу: бабах — и в ферзи. Извините, но пешка E2-E8 не ходит…

              Решение этой задачи необходимо, конечно же, не только для графического интерфейса пользователя, но практически везде, где есть обработка текста, файловая система или хотя бы текстовые сообщения об ошибках.
              Это с какого-такого перепугу? Файловой системе — это не нужно: при использовании UTF-8 подход «имя файла — это произвольная последовательность байт, не включающая в себя символов '\0' и '\'» — отлично работает. Переводить же низкоуровневые сообщения об ошибках — глупость несусветная: для них главное — возможность засунуть их в Гугл или Яндекс, чем перевод будет активно мешать.

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

              Будут модули, будут опциональные компоненты — тогда и можно будет говорить о локализации или графике. А пока — нет.


              1. sena
                24.11.2017 14:43

                Ну и? Кто будет это делать? Кстати почему это «телефоны к ним не относятся»? ICU отсуствует в Android NDK — ровно по причине того, что её размеры слишком велики

                Для встраиваемых систем уже есть обрезанные версии библиотек на любой вкус. Для телефонов же 20МБ это не проблема, о чём вообще разговор???
                Файловой системе — это не нужно: при использовании UTF-8 подход «имя файла — это произвольная последовательность байт, не включающая в себя символов '\0' и '\'» — отлично работает.

                При глобальном использовании UTF-8 никакой проблемы и не возникло бы изначально, но (к сожалению) это не так.


              1. DistortNeo
                24.11.2017 15:03

                Файловой системе — это не нужно: при использовании UTF-8 подход «имя файла — это произвольная последовательность байт, не включающая в себя символов '\0' и '\'» — отлично работает.

                Проблема в том, что не любая последовательность байт является корректной строкой UTF-8. Напомню, что в Linux имя файла — это набор байт, а в Windows — UTF16 (раньше была UCS2). И способов обрабатывать это кросс-платформенно просто не существует.


                1. khim
                  24.11.2017 19:47

                  Проблема в том, что не любая последовательность байт является корректной строкой UTF-8.
                  Однако любая последовательность байт является корректным именем файла.

                  в Windows — UTF16 (раньше была UCS2).
                  И сейчас, на самом деле, UCS2. Невалидные UTF16-названия файловая система принимает на ура, независимость от регистра тоже распространяется только на символы с кодами до 65535 и т.д. и т.п. Так что… это только всякие диалоги открытия файлов делают вид, что там UTF16.

                  Если вы GUI не делаете, то и юникод вам, в общем, не нужен.

                  И способов обрабатывать это кросс-платформенно просто не существует.
                  Ну это к Microsoft'у вопросы.


            1. 0xd34df00d
              24.11.2017 21:05

              Сегодня, на секундочку, 2017 год и отсутствие такой, в сущности, базовой функциональности это какой-то позор…

              Она далеко не везде и не во всех применениях базовая. Из личного опыта — оно нужно, наверное, процентах в пяти задач, которые я решаю.


              1. khim
                24.11.2017 22:05
                +1

                Она далеко не везде и не во всех применениях базовая. Из личного опыта — оно нужно, наверное, процентах в пяти задач, которые я решаю.
                У «адептов рефлексии» — оно базовая. Потому что они обьекты с тремя интами через рефлексию создают, блин.

                А потом удивляются почему GUI тормозит, да.


  1. semenyakinVS
    23.11.2017 16:41

    КДПВ, которую постеснялся вставить в коммент


    1. antoshkka Автор
      23.11.2017 17:09

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

      Должно быть починено Concepts TS, уже будет в C++20.

      За счёт чего будет расширяться комьюнити языка, у которого интеграция нового пакета — задача из категории стыковок космических станций?

      Это общая проблема всех языков программирования. И никакой пакетный менеджер это не решает, ошибки с pip/maven/gem/conan всё еще проще чинить копированием нужного пакета в репозитарий и выкидыванием пакетного менеджера.


      1. DistortNeo
        23.11.2017 20:56

        Это общая проблема всех языков программирования.

        Нет, не любого. В том же C#, например, для подключения библиотеки достаточно одного файла — сборки. В C++ же такой фокус не прокатит — изволь тащить с собой все хедеры, исходники или статические либы, причём последние не только системо-, но и компиляторозависимы. Ещё надо не забыть про условную компиляцию и скорость этой самой компиляции.


        1. Antervis
          23.11.2017 22:00

          Не надо сравнивать. В шарпике цена абстракций перекладывается на рантайм, а в с++ — на время компиляции.


          1. DistortNeo
            23.11.2017 23:42
            +1

            А я и не сравниваю компиляцию во время выполнения со статической компиляцией. Я лишь указываю на то, что сам процесс компиляции С++ очень болезненнен и неэффективен.


            В шарпике цена абстракций перекладывается на рантайм

            Главное премущество C#, да и Java — мухи (язык программирования) отдельно, котлеты (VM) отдельно.


            Было бы удобно, если бы либы распространялись не в виде хедеров/исходников, а виде предкомпилированных платформо-независимых модулей. Тот же clang сначала компилирует в LLVM, а уже потом генерит нативный код.


            1. khim
              24.11.2017 06:30

              Тот же clang сначала компилирует в LLVM, а уже потом генерит нативный код.
              Вот только AST clang'овский зависит как от версии компилятора, так и от целевой платформы. И да, сделать его переносимым не так-то просто, замедление получается весьма заметным.


              1. DistortNeo
                24.11.2017 09:20

                > И да, сделать его переносимым не так-то просто

                Не спорю. C/C++ рассматривается как язык под любую платформу и железку.
                Но я уверен, что конкретно под массовые платформы x86/x64/ARM64 решение придумать можно.


                1. khim
                  24.11.2017 14:05

                  Но я уверен, что конкретно под массовые платформы x86/x64/ARM64 решение придумать можно.
                  Вы вообще сколько с компилияторами общались, извините? Откуда эта уверенность взялась? Рассмотрите простую программу:
                  struct Point {
                    int x;
                    int y;
                  };
                  extern void Do_Something(Point what, int how);
                  void Adapter(int x, int y) {
                    Do_Something({x, y}, 42);
                  }
                  
                  Так вот на x86 вам нужно будет вынуть два числа со стека, засунуть туда 42, после чего добавить туда же x и y, на ARM — нужно будет просто записать в r2 42 и сделать jmp, на x86-64 — вам нужно будет скомбинировать два аргумента в один. Да, ёлки ж палки — посмотрите сами! И? Как вы это всё в одно AST собрались засовывать?

                  Нет, это сделать можно (а в программировании вообще мало чего нельзя сделать в принципе, никогда) — но это полкомпилятора придётся переделывать!

                  Вся информация — описана в Википедии — это не какая-то супесекретная информация…

                  И это — ещё простой случай! А рассмотрите вариантик посложнее:
                  #include <cstdio>
                  template<int n> struct confusing
                  {
                      static int q;
                  };
                  template<> struct confusing<4>
                  {
                      template<int n>
                      struct q
                      {
                          q(int x)
                          {
                              printf("Separated syntax and semantics.\n");
                          }
                          operator int () { return 0; }
                      };
                  };
                  int main()
                  {
                      int x = confusing<sizeof(x)>::q < 3 > (2);
                      return 0;
                  }
                  Ничего что у вас на x86 confusing<sizeof(x)>::q — это функция, а на x86-64 — переменная. Нормально так? Всё ещё горите желанием придумать решение «под массовые платформы x86/x64/ARM64»?

                  Нет уж, извините. Либо у вас ваши модули будут, фактически, ахивами со слегка обработанными исходниками, либо вам весь язык придётся переделывать. Снизу доверху.


                  1. Kobalt_x
                    24.11.2017 14:30

                    Переделывать придется только фронтенд компилятора на работу с AST/ir, который это допускает, от вендоров нужен будет парсить фронтендера и собственно оптимизации этого AST/ir пример llvm бэкенды какие угодно оптимизации над ir какие угодно. «Ничего что у вас на x86 confusing<sizeof(x)>::q » ничего, кода в модуле нет, символы останутся оба, оптимизатор AST/ir скипнет это нафиг на этап кодогенкрации, кодогенератор подставит то что нужно в зависимости от sizeof. p.s. и в x86 и в x86-64 sizeof(int)==4 тут бы сравнивать size_t/ptrdiff_t


                    1. khim
                      24.11.2017 20:06
                      +1

                      p.s. и в x86 и в x86-64 sizeof(int)==4 тут бы сравнивать size_t/ptrdiff_t
                      Да, извиняюсь, недоглядел. Спрасиба за замечание.

                      Переделывать придется только фронтенд компилятора на работу с AST/ir, который это допускает
                      Проблема в том, что «AST/ir, который это допускает» — это, фактически, голая последовательность токенов и всё. При желании можно устроить программу, которую можно распарсить только на платформах, удовлетворяющих какому-нибудь хитрому условию.

                      «Ничего что у вас на x86 confusing<sizeof(x)>::q » ничего, кода в модуле нет, символы останутся оба, оптимизатор AST/ir скипнет это нафиг на этап кодогенкрации, кодогенератор подставит то что нужно в зависимости от sizeof.
                      До этапа кодогенерации ещё дожить надо — а вы пока не рассказали, как вы AST строить собрались, если для синтакцического разбора нужно умеить решать уравнения на эллиптических кривых — причём со входными данными, приходящими от целевой платформы.

                      Не забудьте, что там вместо банального sizeof может стоять вызов любой constexpr функции, а дальнейшее дерево зависит от результата вычислений оной функции.

                      clang-format имеет много подобных чудес, так как разобрать (то есть даже синтаксически разобрать, просто АСД построить!) программу на C++ можно только имея информацию о той платформе, на которой вы программу хотите запускать.


                      1. Kobalt_x
                        24.11.2017 23:04

                        Я если честно всё равно не въехал в чём проблема, делаем ноды в ast типа «я не знаю что это» в ноде лежит ссылки на machine dependant expressions с guardom по этому expression(в вашем случае ваши классы confusing) сами (т.е классы) разбираются.
                        Во время кодогенерации эта шняга проходится, и тупиковый вариант выкидывается.
                        Вроде тупые оптимизации ast а ля пропагация констант, сворачивание методов, эта штука может переживать, про сложные сказать не могу.
                        С constexpr тоже самое.

                        «При желании можно устроить программу, которую можно распарсить только на платформах, удовлетворяющих какому-нибудь хитрому условию.»
                        можно, в этом случае будет колбаса-последовательнось токенов, которая в конце будет содержать кучу листов c guardами идущих в разобранные методы. Длина колбасы может быть большой, но и с текущей ситуацией есть template бомбы, от которых и gcc,clang,msvc тупо дохнут, кто же спорит, вопрос насколько это часто встречается на практике


                        1. khim
                          24.11.2017 23:50

                          Я если честно всё равно не въехал в чём проблема
                          А я не могу понять чего вы не понимаете. Но попробую разобрать подробнее. У меня есть ощущение, что вы краем глаза на пример взглянули и даже не подумали о том — какое здесь будет AST.

                          А проблема в том, что дерево будет разным. Ну вот совсем разным.

                          В одном случае q — это шаблонная функция. И в AST это будет примерно представлено как:
                            function: name = "q"
                            children:
                               specialization - "<3>"
                               parameters: "2"
                          

                          В другом случае — это переменная. И AST будет примерно таким:
                             operator: name = ">"
                             children:
                                 left: "q < 3"
                                 right: "(2)"
                          

                          Ну и, понятно, левое выражение тут — это тоже operator (с именем "<" и двумя аргументами — «q» и «3»).

                          Понимаете? У вас не просто типы нод в AST отличаются! У вас структура AST отличается! В одном случае «наверху» — функция "q" и у неё два ребёнка (специализация <3> и параметры (2)), в другом — это "operator>" и него два других ребёнка (ещё пара выражений — q<3 и (2)).

                          И для того, чтобы сделать выбор — вам нужно знать: была выбрана частичная специализация — или нет.

                          Да чёрт с ним, этим примером — он специально сделан так, чтобы оба варианта были валидны.

                          Что ваш компилятор должен сделать с кодом:
                          int x = confusing<sizeof(x)>::q<3;
                          или с кодом
                          int x = confusing<sizeof(x)>::q<3>;
                          Ведь в зависимости от того что такое есть q — этот код может быть валидным или не валидным! А если этот x — у вас constexpr, то это может сделать валидным/невалидным что-то ещё. И так далее, по цепочке.

                          Вроде тупые оптимизации ast а ля пропагация констант, сворачивание методов, эта штука может переживать, про сложные сказать не могу.
                          Какие, к бесу, «тупые оптимизации» вы собираетесь производить, если вы дерево разбора, блин, построить не можете! Вы не знаете — что есть что в этой конструкции! Функция, оператор, шаблон — что где, как с этим жить? Ничего не известно!

                          Длина колбасы может быть большой, но и с текущей ситуацией есть template бомбы, от которых и gcc,clang,msvc тупо дохнут, кто же спорит, вопрос насколько это часто встречается на практике
                          Сплошь и рядом. Ситуация когда код нормально работает на ILP32 и даже не парсится LP64 (или наоборот) — вполне типичны. А ещё больше случаев когда код таки парсится — но по другому и в результате не компилируется.

                          Проблема в том, что грамматика C++ очень сильно зависит от контекста. Угловая скобочка может быть либо угловой скобкой, либо банальным опереатором меньше. Скобки могут использользоваться для указания параметров функции, либо просто для залания проиритетов операций. А уж сколько всего весёлого бывает с фигурными скобками!

                          Чтобы правильно всё это распарсить вам нужно знать — какие частичные специализации отработали, а какие нет. И что они вернули.

                          Вы же предлагает всё это отложить на момент, когда библиотеку будут пытаться использовать. Плохое решение. Не всем нужен LTO и не все могут себе его позволить. И ещё меньше кому нужна «работающая» библиотека, которую нельзя подключить, так как из неё вдруг ошибки компиляции лезут.

                          Можно, наверное, опять-таки, разработать некоторый диалект языка C++, где этих проблем не будет — но это отдельная история и даааалеко не факт, что этот диалект будет популярен…


                          1. Kobalt_x
                            25.11.2017 03:29

                            «Какие, к бесу, «тупые оптимизации» вы собираетесь производить, если вы дерево разбора, блин, построить не можете! Вы не знаете — что есть что в этой конструкции! Функция, оператор, шаблон — что где, как с этим жить? Ничего не известно!» — именно такой тип и будет expression с описанием хз что-это и c ребрами guardами на ваши confusingи. Сами специализации уже будут преобразованы в ast.
                            Будет expression:«confusing<sizeof(x)>::q<3>»
                            children «confusing<sizeof(x)>::q<3 >» gurard:«sizeof(int)=4»
                            children «confusing<sizeof(x)>::q<3>» guard:«sizeof(int)!=4»

                            «Проблема в том, что грамматика C++ очень сильно зависит от контекста» Да зависит, но это не значит что ничего вывести доступных на момент компиляции ограничений нельзя.
                            Напомню что синтаксис определяется грамматикой, а вот интерпретация этого синтаксиса семантикой, грамматика у cpp вроде как контекстно-свободная.

                            «Вы же предлагает всё это отложить на момент, когда библиотеку будут пытаться использовать.»
                            А типа сейчас не так? в простынях ifdefов и шаблонов наружу?
                            Причём тут lto мы компилируем единицу трансляции, если компилируем в обычном режиме, то компилятор тупо вырезает неверные пути из ast и спамит ошибками если достижимы вершины с ошибками, если lto то будет больше проходов


                            1. Kobalt_x
                              25.11.2017 03:37

                              *несмотря на то что сам язык контекстно зависим...(не успел дописать)


                              1. khim
                                25.11.2017 05:15

                                Не знаю что вы там хотели дописать, но написали вы чушь. Грамматика C++ — не является контекстно-свободной. Потому и GCC от bison'а отказался и у clang'а свой собственный «ручной» парсер.

                                Можете на stack overflow почитать — там формально доказывается, что грамматика не просто не является контекстно-свободной, а она вообще — полна по Тьюрингу! То есть мы в принципе не можем понять — будет данная программа синтаксически валидна на всех платформах или нет.

                                И нет — речь не идёт о том, чтобы разобраться с семантикой. Речь именно о парсинге.

                                А вот есть ещё чудесный пример где AST некоторого участка C++ кода зависит от описания typedef'а случившегося после этого участка кода.

                                Какая тут, нафиг, контекстно-свободность…


                            1. khim
                              25.11.2017 04:59
                              -1

                              Вам бы, блин, политиком быть. Это там ценится двоемыслие.

                              Рекомендую переписать то, что вы написали 100 раз на доске, читая то, что вы написали — вслух и с выражением.

                              «грамматика у cpp контекстно-свободная»… «зависит от контекста»…
                              «зависит от контекста»… «контекстно-свободная»…
                              «контекстно-свободная»… «зависит от контекста»…

                              Я не знаю, блин, сколько раз нужно прочитать эти две фразы, но после какого-то повторения (может быть 1000го) до вас должно-таки дойти, что «контекстно-свободная» и «зависит от контекста» — это таки две несовместимых вещи!

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

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

                              Простейший, блин, вопрос на собеседовании. Рассмотрим такую функцию:

                              template<class T>
                              auto my_begin(T& t) {
                                typename T::iterator i = t.begin();
                                return i;
                              }
                              
                              Зачем у нас в третьей строчке написано слово typename и почему без него нельзя обойтись?

                              Ответ: потому что грамматика C++ не является контекстно-свободной и для того, чтобы шаблонную функцию вы вообще смогли распарсить вам нужно указать контекст: является ли тот или иной идентификатор обычной переменной, типом (указывается с помощью typename), или шаблоном (указывается с помощью template.

                              Но в случае, если код — не шаблонный такой информации у компилятора нет и он должен выяснять — к какому из трёх классов относится тот или иной идентификатор задействуя дополнительную информацию из семантики C++.

                              В примере, который я привёл в зависимости от контекста вы либо парсите кусок кода как вызов operator> от вызов operator< — либо просто как вызов фунции. Куда уж дальше-то на дорожке к контекстной несвободности?

                              А типа сейчас не так? в простынях ifdefов и шаблонов наружу?
                              В случае с шаблонными библиотеки, поставляемые в исходниках — да, так и есть. Но подавляющее большинство библиотек — устроены не так.

                              Причём тут lto мы компилируем единицу трансляции, если компилируем в обычном режиме, то компилятор тупо вырезает неверные пути из ast и спамит ошибками если достижимы вершины с ошибками, если lto то будет больше проходов
                              Проблема в том, что в любой достаточно сложной программе на C++ всегда есть какие-то «вершины с ошибками». То ли у вас шаблоны «не так» инстанциируются, когда «sizeof(void*)» != «sizeof(long)», то ли у вас специализации под «signed char» нет, то ли ещё какая бяка случается.

                              Сейчас такой код тупо компилируют на нескольких платформах и если на всех «нужных», при данных на них параметрах платформы всё парсится и собирается — то и хорошо. А появится ещё какая-нибудь платформа — выпустим patch. Половина ошибок в boostе этому посвящена.

                              Вы же хотите заставить людей писать код, который гарантированно распарсится и соберётся под любую платформу, блин.

                              Где вы таких программистов найдёте? Тут никак убедить писать программы без UB не удаётся — а вы хотите заставить все существующие программы переписать с полноценной разметкой typename и template в каждой второй строке.

                              Никто не будет этого делать, тут даже обсуждать нечего.


                            1. khim
                              25.11.2017 05:26

                              Будет expression:«confusing<sizeof(x)>::q<3>»
                              children «confusing<sizeof(x)>::q<3 >» gurard:«sizeof(int)=4»
                              children «confusing<sizeof(x)>::q<3>» guard:«sizeof(int)!=4»
                              Только заметил.

                              О боги олимпа! Откуда у вас в строке с «sizeof(int)!=4» взялась строка «confusing<sizeof(x)>::q<3>»?

                              В том-то и дело, что если sizeof(int)==4, то строка у нас разбивается при разборе на следующие три куска:
                              «confusing<sizeof(x)>::q» «<3>» и «(2)»

                              А если sizeof(int)!=4, то всё будет по-другому, куски будут такие:
                              «confusing<sizeof(x)>::q<3» «>» «(2)»

                              Вы не сможете в варианте с sizeof(int)!=4 ничего приписать выражению «confusing<sizeof(x)>::q<3>», потому что там нет этого выражение. Там другое дерево разбора и знак больше — уехал вообще в другу ноду!


                  1. DistortNeo
                    24.11.2017 14:54

                    Ничего что у вас на x86 confusing<sizeof(x)>::q — это функция, а на x86-64 — переменная. Нормально так? Всё ещё горите желанием придумать решение «под массовые платформы x86/x64/ARM64»?

                    Увидительно, что ни один компилятор ещё не дорос до того, чтобы во всех случаях свести программу к пустой — ведь программа ничего не вводит и ничего не выводит.


                    В любом случае, путь к универсальному LLVM под основные платформы я считаю наиболее разумным.


                  1. 0xd34df00d
                    24.11.2017 21:09

                    Так AST и есть фактически архив со слегка обработанным исходником. Там ещё никакой специализацией шаблонов не пахнет, не то что кодогенерацией.

                    Правда, теперь мне стало интересно, как вообще представляется AST в компиляторах плюсов, учитывая, что парсинг плюсов не что что контекстно-зависим, а вообще полон по Тьюрингу (и с учётом вот приведённых вами случаев).


                    1. khim
                      24.11.2017 22:16

                      Правда, теперь мне стало интересно, как вообще представляется AST в компиляторах плюсов
                      Как представляется — это не так интересно. AST как AST, там ничего суперхитрого нету.

                      учитывая, что парсинг плюсов не что что контекстно-зависим, а вообще полон по Тьюрингу (и с учётом вот приведённых вами случаев).
                      А вот это вот — другой вопрос. GCC какое-то время пытался бороться с bison'ом, обвешивая его хуками, но в конечном итоге сдался. А в clang'е — с самого начала всё было под «работу на разных уровнях» заточено.

                      Насколько мне известно все парсеры C++ в современных компиляторах написаны руками и могут вызывать более поздние стадии (включая выполнение constexpr-функций, да). А иначе никак — иначе C++ не распарсить.

                      То есть в компиляторах C++ нетне может быть) отдельной стадии построения AST. Фактически парсер и компилятор работают как сопрограммы (хотя оформлено это в разных компиляторах по разному).


            1. 0xd34df00d
              24.11.2017 07:30

              Мой одногруппник тусовался на базе ИСП РАН, если я правильно помню, и делал что-то такое как раз, что-то вроде дистрибутива или метода распространения программ в виде LLVM IR. Было то лет пять назад, и, как видите, к успеху не пришло.


              1. khim
                24.11.2017 14:10

                Да вот вам публичный вариант. Читайте — радуйтесь.

                Все эти проекты упираются в одну простую вещь: им приходится язык очень сильно изуродовать. Существующие библиотеки с этим делом особо не поиспользуешь (я имею в виду уже собранные и присутствующие в системе), часть возможностей языка отсутствует — и нафига оно такое кому нужно? Очередной C++/CLI? Так один уже есть…


            1. Antervis
              24.11.2017 12:22

              Так а какой выигрыш тогда будет получен? Сериализация и десериализация промежуточного представления займет дополнительное время, а основной по времени этап — линковка + LTO не сократится.

              Один из этапов компиляции — парсинг «тяжелых» заголовочников для каждой единицы трансляции и так будет оптимизирован с появлением модулей.

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

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


              1. DistortNeo
                24.11.2017 12:51

                Так а какой выигрыш тогда будет получен?

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


                Сериализация и десериализация промежуточного представления займет дополнительное время, а основной по времени этап — линковка + LTO не сократится.

                Да, LTO — самая долгая процедура, и ничего с этим не поделать. Это цена за генерацию эффективного кода.


                Но для отладочных билдов самая долгая процедура — парсинг инклюдов.
                И серализация/десериализация промежуточного представления даёт ощутимый выигрыш, иначе бы не было плясок с PCH.


                Один из этапов компиляции — парсинг «тяжелых» заголовочников для каждой единицы трансляции и так будет оптимизирован с появлением модулей.

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


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

                Ну хотя бы так. И чтобы зависимости описывались максимально просто — названиями пакетов.


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

                Java как раз таки работает на огромном числе платформ, и существует много ЯП, которые компилируются в код VM и совместимы с Java.


                1. Antervis
                  24.11.2017 13:05

                  И серализация/десериализация промежуточного представления даёт ощутимый выигрыш, иначе бы не было плясок с PCH.

                  Не путайте. PCH парсится во внутренее представление компилятора (он бы и так и эдак туда парсился). Вы говорите о компиляторонезависимом представлении.
                  Ну хотя бы так. И чтобы зависимости описывались максимально просто — названиями пакетов.

                  пользуйтесь conan, например. conan install --build-missing разрешит зависимости для всех популярных пакетов.
                  Java как раз таки работает на огромном числе платформ

                  Java работает только основных десктопных и мобильных платформах. Без embedded.


                  1. DistortNeo
                    24.11.2017 14:17

                    Не путайте. PCH парсится во внутренее представление компилятора (он бы и так и эдак туда парсился). Вы говорите о компиляторонезависимом представлении.

                    Это был контраргумент на "Сериализация и десериализация промежуточного представления займет дополнительное время". Я утверждаю, что это, наоборот, даёт выигрыш в итоге.


                    пользуйтесь conan, например. conan install --build-missing разрешит зависимости для всех популярных пакетов.

                    Хочу ещё проще. Реформу самой системы описания проекта и его сборки.


                    Java работает только основных десктопных и мобильных платформах. Без embedded.

                    Сравните доли разработки под x86/x64/ARM/ARM64 со встраиваемыми решениями. Удобное решение под 99% случаев будет всяко лучше, чем неудобное, но покрывающее 100%.


                    1. khim
                      24.11.2017 17:52
                      +1

                      Сравните доли разработки под x86/x64/ARM/ARM64 со встраиваемыми решениями.
                      На C++-то? С учётом всяких Arduino и прочих STM32? Думаю 50/50 будет. А то и вовсе может оказаться, что x86/x64/ARM/ARM64 окажется в меньшинстве.

                      Да и не стоит валить x86/x64/ARM/ARM64 в одну кучу: как я уже писал выше — поддежать хотя бы x86 и x86-64 одновременно это уже огромная проблема. Из неё, собственно, небезизвестный продукт вышел.

                      Удобное решение под 99% случаев будет всяко лучше, чем неудобное, но покрывающее 100%.
                      Создадите «удобное решение» хотя бы для x86 и x86-64 — заходите, будет о чём поговорить. А там — мы ещё 10 диалектов одного ARM'а подтянем (OABI, EABI, HARD-FP, SOFT-PF и всё такое прочее).


                  1. Kobalt_x
                    24.11.2017 14:35

                    «Java работает только основных десктопных и мобильных платформах» Вспоминаем про Java card(SIM карты привет) вспоминаем про зоопарк телефонов в нулевых, которые на 50-100mhz процами и мегабайтами памяти тянули j2me машину


                    1. splav_asv
                      24.11.2017 16:33

                      И там есть полноценный Unicode?


                      1. DistortNeo
                        24.11.2017 16:49

                        Нет, конечно, зачем он там нужен?


                        1. khim
                          24.11.2017 17:56
                          +1

                          Дык и Java там не нужна — потому и нет ёё там. В JavaCard нет даже намёка на Java (какая, к бесу, Java без String'ов, GC и переносимого байт-кода?), в JavaME всё тоже было очень-очень плохо и переносимостью и не пахло (вплоть до того, что приходилось выпускать одни и те же игры выпускать в десятке вариантов под разные телефоны).

                          Увы и ах, но Java — это очень и очень тяжёлое решение, попытки её аппетиты немного урезать приводит к тому, что бо?льшая часть техник перестаёт работать и, фактически, даже низкоуровневые библиотеки использовать невозможно.


    1. eao197
      23.11.2017 19:01

      Однако каждый новый стандарт заставляет грустить.
      Грустить из-за чего? Тут когда из C++14 в C++11 возвращаться приходится, то уже неприятно, хотя C++14 — это совсем небольшой шаг вперед в сравнении с C++11. А уж когда нужно в C++98 окунуться, так вообще как будто в каменный век возвращаешься.
      Не тем козыряют, как по мне. Совсем не тем, чем следовало бы.
      А чем следовало бы?


      1. Kobalt_x
        23.11.2017 19:20
        +1

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


        1. khim
          23.11.2017 22:43

          Предложение на графику — это, похоже, кому-то делать было нечего. Больно и обидно, что на этот бред тратят время, но, как бы сложно придумать правила, которые бы «на корню» отсекали бы подобную чушь, но пропускали бы полезные предложения. Так что приходится терпеть.


      1. Kobalt_x
        23.11.2017 19:20

        del


        1. eao197
          23.11.2017 19:23

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


      1. semenyakinVS
        24.11.2017 00:16

        Грустить из-за чего?


        Из-за того, что обсасывают в основном всякий сахар и введение классов из boost в std. У меня, возможно, мало опыта (объясните если не прав) — однако я не понимаю в чём первостепенная важность переноса классов из плейграундов вроде boost в стандартную библиотеку (насчёт переноса type traits ясно — это временные костыли для рефлексии). В плюсах имеются практически бесплатные абстракции и мощная условная компиляция. Эти механизмы позволяют упростить вопросы стандартизации API.
        До ввода тех же классов многопоточности в стандарт люди писали обёртки. После явления в std нужных классов миграцию выполняли через замену условной компиляции на новые классы стандарта с последующей подгонкой API и полной заменой обёрток на соответствующие классы из std.
        Если что — я говорю тут не про умные указатели, а именно про классы, не связанные напрямую с информацией, полезной на этапе сборки (тут не очень ясно выразился — надеюсь, понятно что я имею в виду)…

        Был бы благодарен за объяснение если я что-то тут не так понимаю.

        А чем следовало бы?


        Вещами, работающими не на ублажение тонких нужд и ленивостей прожжённых пользователей (подчеркну — именно тонких нужд, вроде того же оператора spaceship), а на снижение порога вхождения в экосистему. Чем больше пользователей у языка — тем выше динамика развития экосистемы и тем выше значение языка. С теми же пакетами логика элементарна: из-за сложности интеграции пакетов сплошь и рядом решения велосипедятся, порождая дублирование кода. Да, часто утверждается что истинная причина самописностей — тонкая оптимизация. Мол, язык такой. Нужно тюнинговать детали под себя… Однако если бы пакеты внятно подтягивались — на плюсах писалось бы больше прикладного кода с повторным использование библиотек, что положительно влияло бы на экосистему в целом и на качество пакетов в частности. Люди смелее выбирали бы из разных вариантов при подключении функционала, динамичнее была бы конкуренция между разработчиками пакетов.

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


        1. khim
          24.11.2017 01:37

          Наши недостатки — продолжение наших достоинств. Огромное преимущество C++ — то, что у него есть несколько независимых реализаций. Это же — огромный недостаток.

          В частности всё, что вы описали — отсюда, собственно.
          если бы пакеты внятно подтягивались
          Microsoft: ну понятно же — nuget — наше все.
          Debian: вы, что, оху-, нет, охре-, нет… совсем белены обьелись? C# для работы с пакетами на C++? Вот, отличное решение.
          Gentoo: Это чтобы одну опцию переключить вам нужно исходники править? Да это вы тут белены обьелись! Вот у нас — всё пучком.
          Google: Ну нет, так мы не договаривались. В ваших этих shell-скриптах утонуть можно. Вот же есть простая система.
          Android: какая ж она «простая», если даже библиотеку под две платформы собрать — проблема? Вот у нас — всё очень гибко где нужно и прямо — где не нужно.
          Ну и так далее.

          И это я ещё всяких мелких вендоров не вспомнил…

          В том-то и дело, что надстройка — у C++ одна (хотя и большая), а того, что «ниже ватерлинии» — десятки, если не сотни!

          Ну и что тут комитет по стандартизации может сделать? Да любое предложение будет до конца века обсуждаться!


        1. 0xd34df00d
          24.11.2017 07:37

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

          Я как раз вчера перекладывал некоторый код с хаскеля на плюсы, там что-то вроде описания AST, и типов этак под сотню. В общем, писать руками 100 * 6 операторов (==, !=, <, >, <=, >=) — очень сомнительное удовольствие. А потом ещё функции для отображения на экран надо будет написать, для хеширования и для всякого ещё. Как подумаю — уже пальцы немного сводит.

          А в хаскеле есть тупо deriving (Show, Eq, Ord). И ещё есть deriving (Generic), после которого можно делать, скажем, deriving (Hashable). И, на самом деле, от компилятора нужна только поддержка этого самого Generic, всё остальное может быть сделано в рамках библиотечного кода.

          Короче, нужны метаклассы. Люто нужны. Тогда никакие спейсшипы, никакая вся эта ерунда-костыли-затычки не нужна будет.


        1. eao197
          24.11.2017 08:56
          +2

          Из-за того, что обсасывают в основном всякий сахар и введение классов из boost в std.
          Ну вот даже тут, в комментариях уже прозвучала мысль о том, что variadic templates в С++ — это всего лишь синтаксический сахар. Возможно, эту мысль распространяют мегагуру, которые и на C++98 с Boost.Preprocessor в обнимку могли генерировать имитацию шаблонов с переменным количеством параметров. Но вот для простых смертных variadic templates стали тем, что перевело использование таких шаблонов из области высокой теории в область обыденной практики. Аналогично и с лямбдами: кто-то мог написать свой Boost.Lambda и получал от этого кайф, кто-то мог использовать Boost.Lambda и мог думать, что в языке лямбды уже есть. А для кого-то лямбды, которые можно просто брать и использовать, появились только с C++11.

          Что до переноса классов из Boost-а в stdlib, то одна из задач stdlib — это предоставление словаря, который могут использовать разработчики сторонних библиотек/компонентов. Чтобы если в библиотеке A создается умный указатель на хэш-таблицу, а в библиотеке B этот указатель используется, программистам не приходилось делать конвертеры из типов библиотеки A в типы библиотеки B (а для С++98 это приходилось делать постоянно). Так что это хорошо, что список типов в stdlib постоянно расширяется и туда попадает то, что уже было проверено на практике.
          тут не очень ясно выразился — надеюсь, понятно что я имею в виду
          Не понятно.
          Вещами, работающими не на ублажение тонких нужд и ленивостей прожжённых пользователей (подчеркну — именно тонких нужд, вроде того же оператора spaceship), а на снижение порога вхождения в экосистему.
          По моему опыту, как раз то, что добавили в C++11, самым значительным образом упростило вход в язык программирования.

          Что до экосистемы в целом, в том числе до пакетного менеджера, то здесь возможности коммитета ограничены в принципе. Добавим сюда еще и то, что передача развития C++ под работу коммитета произошла очень давно (начало работы коммитета — это 1989-1990-й годы). Тогда такой проблемы не существовало в принципе. И нужно было увидеть, как развиваются другие языки и экосистемы, чтобы осознать важность build tool-ов и package manager-ов. И как раз в этом направлении в C++ движуха сейчас активна как никогда. Возможно, даже коммитет начнет в этом направлении что-то делать.

          А вообще: язык развивается за счет своего коммьюнити. Если вам лично нужно что-то, то вы сами можете предложить то, что вам нужно. Если вы этого не хотите/не можете сделать, то, поскольку язык развивается сообществом, вы будете пользоваться тем, что предложили и продвинули другие.


          1. semenyakinVS
            24.11.2017 23:08

            Возможно, даже коммитет начнет в этом направлении что-то делать


            Думаю, меня и других страдальцев расстраивает то, что в публикациях мало выделяются подвижки в интересующих нас направлениях. Тема модулей и менеджеров пакетов стабильно обсасывается в комментариях — однако крайне редко мелькает в самих публикациях.

            Глянул даты выходов пакетных менеджеров для ведущих языков. Действительно, пакетные менеджеры NPM (для Java Script) и PIP (для Python) вышли в районе 2010 года. Однако Maven (для Java) существовал с 2004 года… Можно ещё вспомнить — пусть и не совсем по теме — пакетные менеджеры Linux. Важность упрощения подключения модулей и сборки мультимодульного проекта, как по мне, очевидна. Данный вопрос не возник внезапно когда другие языки начали выкатывать свои менеджеры.

            Ну вот даже тут, в комментариях уже прозвучала мысль о том, что variadic templates в С++ — это всего лишь синтаксический сахар


            Тут абсолютно согласен с вами. Упрощение метапрограммирования — важное направление, и тут мы так же очень долго ждём концептов. Про лямбды — тоже согласен. Это было важное нововведение. Они выступают главным блочком одной из парадигм программирования.

            Однако С++11 де юре вышел шесть лет назад. Для индустрии это громадный срок. И с тех пор подвижки как-то забуксовали.

            Что до переноса классов из Boost-а в stdlib


            Ага… Аргумент про преобразование типов хороший, спасибо.

            Не понятно


            Да, тут какую-то глупость написал… Пытался сформулировать принцип проведения границы между более и менее важными классами для перенесения в stdlib (как по мне, тут включение многопоточности менее важно, включение умных указателей — более важно). Сформулировать плохо получилось.

            язык развивается за счет своего коммьюнити


            Аргумент из категории «в начале сними лучше, а потом критикуй кино» — но отчасти справедливо.

            Я пробовал писать свой пакетный менеджер, а также некоторое время пробовали разрабатывать пакетный менеджер совместно с товарищем theambient. У нас возникли разногласия — theambient продолжил работу над своим менеджером сам, а я немного со своим поковырялся, споткнулся о шаблоны и поставил работу над проектом на долгую паузу.

            В данный момент я с переменным успехом штурмую совершенно другую индустрию. Если не выйдет и доведётся-таки выбирать программирование делом жизни — буду бороться за пакетные менеджеры).


            1. khim
              24.11.2017 23:59

              Пытался сформулировать принцип проведения границы между более и менее важными классами для перенесения в stdlib (как по мне, тут включение многопоточности менее важно, включение умных указателей — более важно).
              С многопоточностью ситуация забавная. Появление модели памяти и mutexов и atomicов, позволяющей писать переносимые библиотеки, надёжно работающие в многопоточном окружении — черезвычайно важно, важнее, чем появление «умных указателей». А вот собственно примитивы для работы с потоками — не так важны.

              Но, согласитесь, было бы глупо если бы язык предоставил mutex'ы и atomic'и — но не предоставил никакого способа создать поток… Считайте, что thread вы получили «в нагрузку»…


            1. ZaMaZaN4iK
              25.11.2017 13:11

              По части пакетного менеджера сейчас очень хайповым является Conan.


            1. eao197
              25.11.2017 13:15

              Тема модулей и менеджеров пакетов стабильно обсасывается в комментариях — однако крайне редко мелькает в самих публикациях.
              А чему тут мелькать? Работа вокруг Modules TS активно идет. Экспериментальную поддержку модулей делают в VC++, clang и GCC. В инструменте для сборки проектов build2 даже реализовали поддержку проектов с C++ными модулями. В общем, работа кипит. Просто ее результаты пока промежуточные и не видны широкой публике.

              С менеджерами зависимостей сейчас вообще активная движуха. Такой еще никогда не было в мире C++. Проблема только в том, что не понятно, кто победит :)
              Можно ещё вспомнить — пусть и не совсем по теме — пакетные менеджеры Linux.
              Как по мне, так это одна из основных причин, по которым штатного менеджера зависимостей для C++ пока нет: огромное количество C++ников разрабатывает код исключительно под Unix-ы и принципиально не желает пользоваться чем-то отличным от штатных пакетных менеджеров их любимых дистрибутивов. И их не волнуют, что есть другие дистрибутивы с другими менеджерами. И уж тем более их не волнуют другие ОС.
              Однако С++11 де юре вышел шесть лет назад. Для индустрии это громадный срок. И с тех пор подвижки как-то забуксовали.
              Для индустрии шесть лет — это не так уж и много. Даже если сравнивать с возрастом самого С++. Есть куча проектов, которые даже не начинали на C++11 переводить. И, подозреваю, часть из них так и не переведут.

              Кроме того, что значит «забуксовали»? Стандарты стали выходить каждые 3 года. Такого в мире C++ еще никогда не было. Но, что еще более важно, начиная с C++14 стала происходить совсем уникальная штука: поддержка нового стандарта практически сразу была доступна в мейнстримовых компиляторах к моменту публикации официального стандарта. VC++ здесь, конечно, был позади GCC и clang, но уже для C++17 обещает серьезно подтянуться.


              1. Antervis
                25.11.2017 15:30

                VC++ здесь, конечно, был позади GCC и clang, но уже для C++17 обещает серьезно подтянуться.

                судя по текущему состоянию дел, он скорее не подтянется, а еще больше отстанет. clang/gcc уже несколько месяцев поддерживают c++17 полностью, в то время как судя по mdsn поддержка с++17 в последней студии примерно на 50%


                1. eao197
                  25.11.2017 15:40

                  Во-первых, у вас устаревшая информация о том, как развивается поддержка современного C++ в VC++: инфа от 15-го ноября сего года.

                  Во-вторых, по сравнению с тем, как быстро появлялась поддержка предыдущих стандартов в VC++ (начиная с C++98) — это все просто огромный прогресс для VC++.


                  1. Antervis
                    25.11.2017 16:03

                    Во-первых, у вас устаревшая информация о том, как развивается поддержка современного C++ в VC++: инфа от 15-го ноября сего года.

                    With VS2017 version 15.5, MSVC has implemented about 75% of C++17 core language and library features

                    Всё равно далеко не в лидерах.


                    1. khim
                      25.11.2017 16:13
                      +1

                      Всё равно далеко не в лидерах.
                      Подтягиваться:
                      1. Медленно перемещаясь, приближаться к чему-либо.
                      2. Догонять ушедших вперед, подтягивать отставших.

                      Где вы тут лидерство увидели?

                      P.S. Вообще-то знание языка на котором ведётся дискуссия — необходимое условие для того, чтобы её можно было вести… ну так считается.