1. C++ / Говнокод #17925

    +57

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    #include <iostream>
    #include <stdexcept>
    
    template<std::size_t N>
    static int constexpr date_component(const char (&s)[N], int i, bool last, int max) {
      return 
        (i + 2 + (last ? 0 : 1) >= N) 
            ? throw std::logic_error("Too short date string") :
        (!last && s[i + 2] != ':') 
            ? throw std::logic_error("Cannot find delimiter") :
        (s[i] < '0' || s[i] > '9' ||  s[i + 1] < '0' || s[i + 1] > '9') 
            ? throw std::logic_error("Not a number") :
        ((s[i] - '0') * 10 + (s[i + 1] - '0') > max) 
            ? throw std::logic_error("Too large number") :
                (s[i] - '0') * 10 + (s[i + 1] - '0');
    }
    
    struct time { 
        int hour; int minute; int second; 
        
        template<std::size_t N>
        constexpr time(const char (&datestr)[N]) :
            hour(date_component(datestr, 0, false, 24)), 
            minute(date_component(datestr, 3, false, 60)),
            second(date_component(datestr, 6, true, 60)) 
        {}
    };
    
    struct time constexpr midnight("00:00:00");
    struct time constexpr afternoon("12:00:00");
    
    int main(int argc, char* argv[]) {
        std::cout << "Midnight hour is " << midnight.hour << std::endl;
        std::cout << "Afternoon hour is " << afternoon.hour << std::endl;
    }

    C++ и даты времени компиляции

    Запостил: myaut, 03 Апреля 2015

    Комментарии (21) RSS

    • и это работает?
      Ответить
      • Да :)
        Ответить
        • Мяут - хуяут
          Ответить
        • msvc? или gcc это уже тоже может?
          Ответить
          • В gcc 4.9.1 работает
            Ответить
          • Да тут вроде обычный c++11, ничего платформозависимого.

            P.S. gcc 4.9.1 - всё работает, собралось с ворнингом про сравнение знакового и беззнакового.
            Ответить
            • собралось - это одно. но в С++11 есть много ограничений на constexpr и компилер его может просто проигнорировать и сделать это обычной функцией.

              ты можешь в дизассемблере глянуть - функция есть или ее нет? или проще: строки "00:00:00" и "12:00:00" попали в объектник или нет?
              Ответить
              • Я проверял так: пытался использовать поля полученных time в качестве аргументов целочисленных параметров другого шаблона - инстанциировалось и компилялось.
                Ответить
                • красота.

                  ЗЫ у нас тут встроенщину на С++ переводят. а в gcc 4.8 С++11 еще по умолчанию выключен. надо будет народу сказать -std добавить.
                  Ответить
                  • Как вы вообще живёте без move-семантики, auto, range-based for, фьючерсов, атомиков, умных указателей, etc.?
                    Ответить
                    • Судя по тому, как он рьяно защищал перл - прекрасно.
                      Ответить
                    • LOL. не мой отдел, но прокоментирую. первый приоритет: (в идеале) 100% тестовое покрытие. игрушки для разрабов... это даже не второй приоритет.
                      Ответить
              • > и компилер его может просто проигнорировать и сделать это обычной функцией
                Не может. Если хоть одно ограничение на constexpr не выполнено - свалится с ошибкой компиляции.

                А в дизасме смотреть - не айс. Компилятор и без constexpr выкинет всё это нахуй и оставит только вывод ответа...
                Ответить
                • > Если хоть одно ограничение на constexpr не выполнено - свалится с ошибкой компиляции.

                  Вроде не совсем так. Например, если есть шаблонная constexpr функция, а ты в неё пихаешь не поды, то она просто превратится в рантайм-функцию.
                  Ответить
                  • > Например, если есть шаблонная constexpr функция, а ты в неё пихаешь не поды, то она просто превратится в рантайм-функцию.
                    Хм.. надо попробовать.
                    Ответить
                    • #include <string>
                      #include <iostream>
                      
                      template <class T>
                      constexpr T add(const T& lhs, const T& rhs) {
                          return lhs + rhs;
                      }
                      
                      template <int Value> struct S {
                          static constexpr int value = Value;
                      };
                      
                      int main() {
                          std::cout << add<std::string>("Hello, ", "World!\n");
                          return S<add(0, 0)>::value;
                      }
                      Ответить
                      • Но тут её использовали не в constexpr контексте...

                        Использовать constexpr функцию на не constexpr данных если не нужен constexpr результат вроде бы никто не запрещает, да. Чтобы 2 версии не копипастить.
                        Ответить
                      • А struct time constexpr midnight("00:00:00") таки заставит компилятор вычислить всё это во время компиляции или упасть с ошибкой. Или я не прав?
                        Ответить
                • > Не может. Если хоть одно ограничение на constexpr не выполнено - свалится с ошибкой компиляции.

                  хочется верить.

                  > А в дизасме смотреть - не айс.

                  сам глянул. смотри коммент в низу. работает и на 4.8.2.

                  я не ожидал что компилер бросание исключение съест.
                  Ответить
                  • > я не ожидал что компилер бросание исключение съест.
                    Не совсем -- он просто не трогает эту ветку. Однако если вызвать ее явно так:
                    struct time constexpr bad1("10.30");

                    Получишь неочевидную ошибку:
                    constexpr.cpp:32:30:   in constexpr expansion of ‘time((*""))’
                    constexpr.cpp:23:50:   in constexpr expansion of ‘date_component<1ul>((* & datestr), 0, 0, 24)’
                    constexpr.cpp:8:57: error: expression ‘<throw-expression>’ is not a constant-expression
                             ? throw std::logic_error("Too short date string") :

                    (ну и т.д.)

                    ЧСХ, static_assert в constexpr не присунуть.
                    Ответить
            • даже на 4.8.2 все правильно собралось. и в топку было соптимизировано - даже в сегмент данных ничего не попало. от всего этого счастья осталось:
              ...
                400860:       be 00 00 00 00          mov    $0x0,%esi
                400865:       48 89 c7                mov    %rax,%rdi
                400868:       e8 73 fe ff ff          callq  4006e0 <std::ostream::operator<<(int)@plt>
              ...
                400884:       be 0c 00 00 00          mov    $0xc,%esi
                400889:       48 89 c7                mov    %rax,%rdi
                40088c:       e8 4f fe ff ff          callq  4006e0 <std::ostream::operator<<(int)@plt>
              Ответить

    Добавить комментарий