• Как лучше задать табличную функцию с редкой областью определения?

    Taraflex
    @Taraflex
    Ищу работу. Контакты в профиле.
    всего значений 10-20.

    Если функцию f можно сделать constexpr, то я за switch
    case 100: return f(100); break;

    Для компактности после return ставить break необязательно.

    Если нельзя то за длинный массив.
    Ответ написан
    Комментировать
  • Как лучше задать табличную функцию с редкой областью определения?

    @Mercury13
    Программист на «си с крестами» и не только
    Если аргументы до 100, функция заранее известна и неизменна — чхайте на всё и делайте простым массивом. Именно так, таблицей переходов, внутри устроен switch. Всё, что я пишу ниже — для общего развития.

    Это называется «разреженный массив» (sparse array)

    1. Хэш-таблица (std::unordered_map).
    Преимущество: есть «в коробке», очень быстра.
    Недостаток: ест много памяти.

    2. Я также использую вот такой механизм.
    template <class T>
    class ChunkMap
    {
    public:
        // Data access
        //------------------------------------------------------------------------//
        /// @return  data at index t, or empty value
        T get(size_t t) const;
    
        //------------------------------------------------------------------------//
        /// Sets data at index t (empty value to erase)
        void put(size_t t, T x);
    
        //------------------------------------------------------------------------//
        /// Erases range [0..maxPlus)
        void eraseTo(size_t aMaxPlus);
    
        // Info
        size_t nChunks() const { return fChunks.size(); }
        bool isEmpty() const { return fChunks.empty(); }
    
        //------------------------------------------------------------------------//
        /// @return  the number that is beyond all chunks
        size_t ceil() const;
    
        //------------------------------------------------------------------------//
        /// @return  actual number of records in the map
        size_t size() const;
    
        //------------------------------------------------------------------------//
        /// @return  lowest value in the map; (0, empty) if empty
        std::pair<size_t, T> lowerValue() const;
    
        //------------------------------------------------------------------------//
        /// @return  highest value in the map; (0, empty) if empty
        std::pair<size_t, T> upperValue() const;
    
        //------------------------------------------------------------------------//
        /// @return  (t1, v), t1 <= t;  (0, empty) if none
        std::pair<size_t, T> lowerOrEq(size_t t) const;
    
        template <class Body> void loop(const Body& r) const;
        template <class Body> void loopFrom(size_t aMin, const Body& r) const;
    
        //------------------------------------------------------------------------//
        ///  Loops all data. Body is bool-convertible.
        ///  Return true → go on.
        ///  Return false → stop and return false.
        template <class Body> bool loopBool(const Body& r) const;
    
        void clear() { fChunks.clear(); }
    
        constexpr static T emptyValue() { return std::numeric_limits<T>::max(); }
        static bool isEmptyValue(const T& x) { return (x == emptyValue()); }
    
        constexpr static unsigned chunkSize() { return Chunk::SIZE; }
    
    private:
        struct Chunk
        {
            enum { SIZE = 8 };
            Fix1d<T, SIZE> data;   // мой шаблон, массив фиксированного размера с проверкой на выход за границы
    
            Chunk();
            bool isEmpty() const;
            std::pair<size_t, T> lowerValue(size_t aKey) const;
            std::pair<size_t, T> upperValue(size_t aKey) const;
        };
        typedef std::map<size_t, Chunk> Chunks;
        Chunks fChunks;
    };

    Можно делать и на unordered_map при желании, но мне нужна lowerOrEq().

    Преимущество: экономия памяти, если есть несколько значений рядом.
    Недостаток: больше расход памяти (ненамного).

    3. Вот ещё есть реализация на Java.
    https://android.googlesource.com/platform/framewor...
    Преимущество: серьёзная экономия памяти.
    Недостатки: когда массив велик (тысячи заполненных элементов), снижается скорость доступа. Большие расходы на чистку мусора.
    Ответ написан
    Комментировать
  • Почему в C++ приоритет сравнения выше, чем побитовых логичеких операций?

    maaGames
    @maaGames
    Погроммирую программы
    if( A != 0 && B != 0 )

    if( A & B != 0 )

    Если бы в двух этих примерах приоритет && и & отличался, то ошибок было бы в 100 раз больше, чем сейчас.
    Ответ написан
    Комментировать
  • Почему возникает ошибка LNK2001 Неразрешенный внешний символ символ?

    @Mercury13
    Программист на «си с крестами» и не только
    Как говорят, «или крест снимите, или трусы наденьте». И учите понятие «единица компиляции».
    По какой схеме устроен ваш проект? «Одна единица компиляции» или «много единиц компиляции»?

    Си недалеко ушёл от ассемблеров. А в ассемблерах программа компилировалась по частям и собиралась воедино линкером (компоновщиком, редактором связей) — в те времена кода было много, а данных мало. Многие из ошибок невозможно было определить, не запустив линкер. Си++ пользуется многими из архитектурных особенностей ассемблеров и Си — по крайней мере ни одно из модульных решений не стало рекомендацией (кроме костыля extern template class).

    Но как говорить «переменная/функция есть, такого-то типа и в другой единице компиляции»? Для этого есть прототипы функций и extern-определения переменных. Их обычно вносят в заголовочные файлы с таким требованием: ничего, что находится в заголовочном файле, не должно производить кода. А код производят…
    • Глобальные переменные (без typedef, extern).
    • Нешаблонные функции (кроме inline).
    • Полностью специализированные шаблонные функции (кроме inline).
    • Команда «специализировать шаблон» (template class).

    При этом…
    • Функции в теле struct/class автоматически inline и кода не производят.
    • Для неявной специализации шаблонов существуют обходы — код генерируется дважды, но ошибки не выдаёт.
    • «Свой» хедер обычно включают первым, чтобы убедиться, что в нём нет недостающих зависимостей.

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

    Системы «одна единица компиляции» и «много единиц компиляции» можно комбинировать, но надо знать:
    • Все хедеры, которые производят код, должны подключаться из одной-единственной единицы компиляции. Надо чётко осознавать, из какой, и не подключать из чужих.
    • У библиотеки всё равно должен быть хедер-фасад, не производящий кода и предназначенный для стыковки с другими единицами компиляции.
    Такая конструкция ускоряет полную перекомпиляцию и часто применяется для библиотек, но надо знать: огромные библиотеки вроде SqLite, в 5 мегабайт препроцессированного кода, мешают распараллеливанию компиляции (ибо пока откомпилируется SqLite, остальные процессоры вполне себе соберут остальную программу).

    // В схеме «одна единица компиляции»: ничего не делать.
    // В схеме «много единиц компиляции»: лишняя зависимость; унести в unit1.cpp
    #include <cstdlib>
    
    // В схеме «одна единица компиляции»: убрать extern.
    // В схеме «много единиц компиляции»: завести unit1.cpp, там сделать MyType x;
    extern MyType X;
    
    // В схеме «одна единица компиляции»: ничего не делать.
    // В схеме «много единиц компиляции»: перенести функцию в unit1.cpp, оставив в .h только прототип.
    void XReset() {}
    Ответ написан
    Комментировать
  • Почему возникает ошибка LNK2001 Неразрешенный внешний символ символ?

    15432
    @15432
    Системный программист ^_^
    extern MyType X
    эта строка означает, что переменная с именем X типа MyType уже существует и объявлена в некотором другом .cpp файле, причем глобально.

    TL;DR: уберите extern
    Ответ написан
    Комментировать
  • Как в C++ скрыть определение вспомогательных типов?

    Adamos
    @Adamos
    class MyClass1 
    {
      MyStruct2 member; // компилятору необходимо полное описание структуры - она является частью класса (в частности, влияет на размер объекта в памяти)
      MyStruct2 *member; // компилятору не требуются подробности. Если этот член не используется вне класса - описание структуры спокойно может лежать только в cpp-файле этого класса, больше оно никому не понадобится.
      ... 
    }
    Ответ написан
    Комментировать
  • Как в C++ скрыть определение вспомогательных типов?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    В целом, твой вопрос не имеет точного ответа, т.к. вопрос затрагивает темы вкуса цветных карандашей и просто является риторическим.

    Помимо всей этой воды, что я ниже изложил, еще очень стоит ознакомиться с разделом "SF: Source files" официального гайдлайна:
    https://github.com/isocpp/CppCoreGuidelines/blob/m...
    (Очень советую изучить весь гайдлайн от корки до корки)

    По первому вопросу, коротко: если тип используется по значению - полное объявление типа обязательно, иначе можно обойтись Forward declaration.

    Немного подробнее:

    Существует такой принцип формирования проекта, когда каждый заголовочный файл предоставляет полную информацию о зависимостях. Forward declaration в таком случае или запрещено, или сильно порицается. Каждый заголовочный файл должен обязательно включать в себя заголовочные файлы всех зависимостей. А файл исходного кода должен включать ровно один заголовок - тот, чей интерфейс реализуется в исходном коде.
    Это позволяет сразу видеть все зависимости кода, не париться с размещением файлов, не париться с транзитивными зависимостями, просто не париться, а так же существенно огребать на времени компиляции. Особенно если в проекте разрешен только #include "", а #include <> порицается.
    В качестве примера можно почитать UE4.

    Существует и другой принцип формирования проекта, когда файловая структура отражает макроуровень архитектуры проекта. Скажем, если проект базируется на подсистемах или слоях, каждый слой(подсистема) представляется ровно одним заголовочным мастер-файлом и своей отдельной папкой в файловой системе. Внутри этой папки расположены все внутренние заголовочные файлы подсистемы. Ни один внутренний заголовочный файл не содержит никаких зависимостей, только объявление своего интерфейса. Все зависимости (FD, другие подсистемы или слои, системные заголовки и.т.д.) описывает только мастер-файл, он же в нужной последовательности подключает все внутренние заголовки. Другие подсистемы, равно как и исходный код самой подсистемы, включают в себя только мастер-файл.
    Это позволяет снять всю шелуху с внутренних заголовков и сосредоточить их текст ровно на декларации интерфейса. С другой стороны, ради использования какого-нибудь мелкого типчика всегда приходится подключать всю подсистему, т.к. внутренние заголовки подключать нельзя по правилам формирования проекта и потому что их зависимости неясны.

    В обоих принципах применяется одно очень важное правило: Один класс - один комплект исходного кода с именем самого класса. Это, можно сказать, самый базовый принцип формирования проектов. Классы с инвариантом и богатым функционалом должны быть объявлены каждый в своем отдельном заголовке, имеющим имя класса. Описание функционала каждого такого класса должно лежать в своем отдельном файле исходного кода с именем описываемого класса. Иногда и вовсе требуется несколько файлов исходного кода на один класс, потому что класс выполняет слишком много функций, но разделять его нельзя.
    Этот принцип нередко приводит к проблеме циклической зависимости, когда два класса ссылаются друг на друга и в каждом заголовке необходимо включение второго заголовка. В этом случае помогает или редизайн классов для ослабления зависимостей, или Forward declaration как меньшее из зол.

    С точки зрения компилятора есть только один формат файла - формат исходного кода, который ему и надо обработать.
    С точки зрения человека форматов файла не два, а 3 или 4:
    • .c , .cc , .cxx , .cpp , c++ - формат исходного кода, в котором стоит производить определение интерфейсов и держать все приватные инструменты (код и типы);
    • .h , .hh , .hpp - формат заголовка, в котором подключаются заголовки зависимостей и объявляется интерфейс - ровно то, что может понадобиться в другом коде или не может быть определено в файле исходного кода. И ничего больше;
    • .inl - формат вспомогательного заголовка, в котором производится определение inline функций и сложных шаблонных конструкций;
    • .inc - формат вспомогательного заголовка, в котором описываются форварды, внешние глобальные переменные, константы и прочие данные. Этот формат используется реже всего. Вместо него чаще используют формат заголовка (.h), размещая в нем весь контент .inc файла.


    Если с "человеческими форматами" все должно быть хорошо понятно, то с форматом файла для компилятора стоит уяснить одну тонкость - все эти человеческие шахматы с бубнами и делением на файлы должны складываться в как можно более удобный для компиляции вид. Чем меньше одинаковых #include, тем лучше. Чем меньше #include в целом, тем лучше. Трансляция - дело итак нелегкое.
    Ответ написан
    Комментировать
  • Всегда ли в C++ false == 0, true == 1?

    @Jony1337
    Всегда в C++ false == 0, true == 1
    Ответ написан
    Комментировать
  • Какое нормальное время генерации страницы и ответа сервера?

    @querty
    Время отдачи первого байта до 200 мс - это очень хорошо, но я такого ни у кого не видел. Обычно 350-600. Время можно посмотреть в браузере Network или спец сервисах.

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

    Сам php занимает очень мало время, основное время уходит на запросы к базе. Поэтому при оптимизации имеет смысл измерять именно время ответа на конкретные sql запросы и оптимизировать их.
    Ответ написан
    1 комментарий
  • Какое нормальное время генерации страницы и ответа сервера?

    xSkyFoXx
    @xSkyFoXx
    Если событие происходит быстрее, чем за 150-200 мс - человеку кажется, что событие произошло до его действия.
    Если между действием пользователя и получением результата проходит больше 0.5-1 с., велика вероятность, что это начнёт раздражать пользователя.
    Ваше время генерации совершенно ОК, если речь идёт о >=99% кванитили. Убедитесь только в том, что ваши основные пользователи находятся в восточной Европе, чтобы роутеры+скорость света до Америки/Азии не накладывали большую дополнительную задержку и что JS на клиенте не очень тяжёлый, чтобы задержка на стороне клиента для рендера контента тоже была не очень большой.
    Ответ написан
    Комментировать
  • Нужно ли соблюдать типизацию в PHP?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Это нормальный стиль?

    Это днище.

    Не следует ли избегать приведения типов, а при необходимости явно приводить типы с помощью (int), (bool) или intval, strval и т.п.?

    Следует забыть про существование НЕ явных преобразований типов. Явное же приведение - это норм.

    Как приведение типов влияет на производительность?

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

    Почитайте на досуге: Попросили проверить код, на что смотреть нужно?
    Ответ написан
    Комментировать
  • Нужно ли соблюдать типизацию в PHP?

    27cm
    @27cm
    TODO: Написать статус
    Иногда использую целочисленное значение в качестве флага

    Не норм. Это затрудняет понимание вашего кода. Для булевых значений есть тип bool.

    выполняю арифметические действия с числом, которое получено из БД как строка

    Не норм. Рано или поздно это "выстрелит", а искать и исправлять ошибку будет сложно.

    var_dump('0' == null); // false
    var_dump( 0  == null); // true

    Вывожу целочисленные значения в html.

    Норм.
    Ответ написан
    Комментировать
  • Как выравнить текст по центру?

    HamSter007
    @HamSter007
    HTML/CSS верстальщик
    А вопросы все изощренней и изощренней.

    Так:
    &nbsp;&nbsp;&nbsp;&nbsp;* Текст &nbsp;&nbsp;&nbsp;&nbsp;

    Так:
    &#160;&#160;&#160;&#160;* Текст &#160;&#160;&#160;&#160;

    По высоте:
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    &nbsp;&nbsp;&nbsp;&nbsp;* Текст &nbsp;&nbsp;&nbsp;&nbsp;
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;


    Еще по высоте:
    <br/>
    <br/>
    &nbsp;&nbsp;&nbsp;&nbsp;* Текст &nbsp;&nbsp;&nbsp;&nbsp;
    <br/>
    <br/>
    Ответ написан
    1 комментарий
  • Как лучше сделать, чтоб действие по onMouseOver происходило только один раз при наведении на объект?

    Создайте переменную например counter и при каждом возникновении события увеличивайте её, задайте условие которое будет проверять переменную counter и в зависимости от условия выполнять/не выполнять действия.
    Ответ написан
    Комментировать
  • Как лучше сделать, чтоб действие по onMouseOver происходило только один раз при наведении на объект?

    @666Wolf666
    Можете просто создать переменную и проверять ее значение при наведении, если значение не подходит, то ничего не предпринимать.
    var bool = 0;
        $('#test').mouseover(function(){
            if(bool == 0){
                alert('All is ok');
                bool = 1;
            }
            else{
                alert('stop')
            }
        });
    Ответ написан
    Комментировать
  • Стоит ли на форуме делать редирект по ссылкам на внешние сайты?

    Rou1997
    @Rou1997
    Стоит сделать сразу же, если пока нет применения то можете просто оставить "пустым" (ответ 302), а в будущем может пригодиться для самых разных нужд, для статистики, для показа рекламы, для принуждения пользователей к регистрации, для поддержания уровня паранойи пользователей считающегося релятивно адекватным.
    Ответ написан
    Комментировать
  • Стоит ли на форуме делать редирект по ссылкам на внешние сайты?

    Denormalization
    @Denormalization
    Это делается для того, чтобы:
    - Убрать активную ссылку на внешний ресурс (можно через nofollow)
    - Скрыть referrer при переходе по ссылке.

    Если ничего из этого не нужно, то и делать не стоит.
    Ответ написан
    Комментировать