Задать вопрос
Ответы пользователя по тегу C++
  • Почему возникает ошибка C2512 в конструкторе с std::initializer_list?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас конструктор не передает initializer_list в поле arr[N], а сначала конструирует массив по умолчанию, а потом туда копирует ручками значения из initializer_list. Перед выполнением тела конструктора вся память должна быть выделена и все не иницилизированные явно поля инициализируются по умолчанию.

    В качестве решения можно весь ваш ручной код выкинуть и передать список в конструктор arr:
    static_array(std::initializer_list<type> il)
    		requires std::is_copy_constructible_v<type> : 
            arr(std::forward(il)) {}


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

    Но вообще, можно не расписывать разные конструкторы, а сделать только один static_array(T&& init), где этот init и передавать в конструктор arr.

    Если вы так хотите руками данные копировать через ваш place_at, то вам надо ваш array сделать типа char или uint8_t, выровнять и задать нужный размер через sizeof(type). Простой случай показан тут.

    А вообще, чем вам std::array не нравится?
    Ответ написан
  • Почему окружность получается отрисованной не ровно?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Это называется aliasing. Ну не ложится гладкая окружность (да и наклонные прямые) на прямоугольную сетку пикселей. SDL renderer похоже слишком примитивен и умеет красить только черные и белые пиксели. Если бы он где-то рисовал серые, картинка выглядила бы более гладкой.

    Если вас это качество не устраивает, то вам надо найти какой-то алгоритм рисования окружности по пикселям и руками его реализовать (что-то вроде этого). Или реализовывать (сглаживание) anti-aliasing. Например, можно нарисовать сцену в текстуре в 2-3-4 раза больше нужного размера, потом ее отмасштабировать до размера на экране и уже это показывать.

    Еще где-то пишут, что если использовать GPU а не software рендеринг в SDL то качество получше.
    Ответ написан
    3 комментария
  • Почему не получается вывести тип шаблона?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Проблема в том, что TInput с одной стороны выводится из первого аргумента, там у вас BuildableProperty<...,...,const Cursor&> согласно определению CursorProperty.

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

    Один из способов это починить - в объявлении SetProperty:
    SetProperty(..., typename std::remove_reference<TInput>::type value)


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

    Но вообще, по уму вам бы ваш шаблон BuildableProperty пофиксить. Вот у вас для каких-то случаев надо в нем ссылки использовать. Так может ссылки имеет смысл использовать всегда? Тогда вы в шаблоне BuildableProperty предполагайте что T, TInput - это просто типы, без ссыльности и константности, и внутри где надо расставьте &.

    Не надо для каких-то случаев "передавать" в шаблон ссылки на какие-то типы.
    Ответ написан
    1 комментарий
  • Почему умные указатели нельзя интегрировать в язык?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно, но нужно ли? Польза только в том, что вы экономите 6 симолов (std:: уже можно убрать через using namespace std например). И то, только в случае, когда вам нужен именно вот такой вот указатель. А если вам нужен unique_ptr, а если вам нужен ваш собственный умный указатель, который как-то по другому память выделяет? А если вам надо не make_shared вызывать, а какой-то фабричный метод? Плюс это добавит кучу вопросов вроде, а как будет указатель на указатель? Указатель обычно идет после типа вроде int*, почему shared вы ставите перед ним?

    В общем, возни много, а польза весьма ограниченная.
    Ответ написан
    2 комментария
  • Как ждать в диапазоне атомарных чисел?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    То, что вы описали в комментариях, это буквально блокировка чтения-записи. Функтор читает данные и может выполнятся параллельно несколько раз, но запись может быть только одна и она блокирует все чтения. Решение описано в википедии: 2 мьютекса, один счетчик. Атомиков не надо.
    Ответ написан
    Комментировать
  • Почему возникает ошибка при вызове вирутального метода в "operator="?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Во-первых, оператор не виртуальный.

    Во-вторых, это проблема из-за правил поиска операторов. Они ищутся только в типах, которые участвуют в выражении, т.е. int и WidthProperty.

    Если хотите использовать оператор из родительского класса, надо в дочернем сделать
    using Base::operator=;

    Что бы протащить этот метод в пространство имен дочернего класса, где компилятор его найдет.
    Ответ написан
    1 комментарий
  • Возможно ли как-то обойти ограничение на невозможность создать виртуальный шаблонный метод?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Зачем вам делать виртуальный метод в шаблоне, если вы в шаблоне же определяете, должен ли он что-то делать или нет? Вы можете сделать 2 разных инстанса шаблона: один с функцией, которая что-то делает, и другой, где - ничего не делает. Виртуальность тут не дает никаких дополнительных степеней свободы.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    DeepSeek галлюционирует. Временные объекты живут до конца выражения. unique_ptr начнет уничтожение после выполнения всего выражения.

    Вот ссылки на стандарт:

    make_unique<> является prvalue: https://en.cppreference.com/w/cpp/language/value_c...
    prvalue: a function call or an overloaded operator expression, whose return type is non-reference


    В момент вызова происходит материализация временного объекта: https://en.cppreference.com/w/cpp/language/lifetime

    Temporary objects are created ... in the following situations:
    when performing member access on a class prvalue.


    Там же написано:
    All temporary objects are destroyed as the last step in evaluating the full-expression


    Т.е. возвращенный make_unique объект будет уничтожен только в конце строки.
    Ответ написан
    Комментировать
  • Когда передавать копию callable, а когда через rvalue reference?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    В дизайне интерфейса можно передавать и копию и rvalue refernce. Что выбрать - решать вам, как создателю интерфейса. Если у вас предполагаются использование функций/лямбд без тяжелого состояния (связанные аргументы по значению), то копирование дешевое и не надо его вводить. rvalue reference всегда дешево, но у вас нельзя будет переиспользовать предикат между разными вызовами.

    В функциях из algorithm используется передача по значению, что бы не ограничивать пользователя. Вы можете один раз написать нужный вам предикат и передавать его во все вызовы. Плюс исторически так сложилось. Когда оно все созадавалось, никаких rvalue reference и не было. Потом их добавлять и не стали, потому что в самом частом случае, если лямбду прямо в аргументах задавать, то она практически бесплатно передастся.

    Там не используется передача по ссылке (lvalue reference), потому что это не так универсально в шаблоне. Если у вас какой-то const предикат, вы его в reference не передадите. А делать const & в интерфейсе нельзя, вдруг у вас предикат не константный?

    И, если вы все-таки хотите передать ссылку, то можно передать std::ref(pred), тогда в шаблоне выведется передача по ссылке.
    Ответ написан
    Комментировать
  • Правильно понимаю из статьи про умные указатели?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Похоже на ошибку оформления. Это должен быть вызов функции. В тексте выше даже написано про вызов.

    Тут автор считает, что сначала выполнится new A(), потом new B(), потом конструктор unique_ptr. Если исключение бросит B(), то действительно будет утечка памяти. Объект A, полученный через new умрет еще до оборачивания в unique_ptr. Такой сырой указатель автоматически не удалится.

    Такая последовательность невозможна c С++17:
    In a function call, value computations and side effects of the initialization of every parameter are indeterminately sequenced with respect to value computations and side effects of any other parameter.


    Evaluations of A and B are indeterminately sequenced : they may be performed in any order but may not overlap: either A will be complete before B, or B will be complete before A. The order may be the opposite the next time the same expression is evaluated.


    Но до C++17, действительно, компилятор может перемешать вычисления аргументов как угодно.
    Ответ написан
    Комментировать
  • Код при самостоятельном тестировании работает корректно, а при проверке тестировщиком программа выдает ошибку. В чем может быть проблема?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас неинициализированные переменные mini и maxi. И они используюся такими в сравнениях. Это Undefined Behavior и на разных компьютерах может вести себя по разному. И если вам не повезет и, например, mini окажется каким-то очень маленьким числом, то у вас выдаст не правильный ответ.
    Ответ написан
  • Как реализовать алгоритм на С++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Используйте std::vector. Их можно присваивать как переменные. При этом там под капотом не будет никакого копирования, а просто изменение указателей в данном случае (так как правая часть - временное значение).
    std::vector<int> a, b;
    a = a0;
    b = F(a);
    for (int i = 1; i <= n; ++i) {
      a = G(b);
      b = F(a);
    }


    Если вас напрягает, что функции G и F выделяют память внутри, то можно сделать, чтобы они получали vector, в который надо вернуть значения:
    void F(const vector<int> &a, vector<int>& res);
    void G(const vector<int> &b, vector<int>& res);
    
    std::vector<int> a, b;
    a = a0;
    b = F(a);
    for (int i = 1; i <= n; ++i) {
      G(b, a);
      F(a, b);
    }
    Ответ написан
    Комментировать
  • Почему без std::remove_reference_t не работает?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вообще, не вижу противоречия. У вас же там tfunc&&, его вы пытаетесь к void* привести и к нему применяете remove reference.

    Попробуйте в ваш static assert добавить std::move и он обвалится.
    Ответ написан
    Комментировать
  • Могут ли возникнуть проблемы при одновременном чтении и записи в разных потоках переменной?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ничего страшного не произойдет, да. Просто вы никак не проконтролируете, когда запись из первого потока будет видна во втором потоке. Например, вы тут можете увидеть скачек сразу на 2, или несколько раз подряд одно и то же значение, хоть оно по идее должно постоянно и монотонно расти.
    Ответ написан
    Комментировать
  • Что лучше: static методы или функции?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Посмотрите в этот allStatic: https://github.com/openjdk/jdk/blob/496641955041c5...

    Там написано, почему используются статические методы: Почему-то авторы какого-то проекта HotSpot решили, что плодить namespac'ы плохо. Так что это вызвано соглашениями по стилю в конкретном проекте. Их право.

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

    Еще логично сделать функцию членом класса, если она именно с классом работает. Например, функции фабрики.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Не совсем уверен, потому что кода не хватает в вопросе. Но симптом звучит как "если шаблон определяется не в том же файле, где он объявляется, то ничего не работает". Это частая ошибка на С++ с шаблонами.

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

    Поэтому надо или шаблон объявлять и опеределять в хедере, чтобы оперделения были везде, или в cpp с определениями указать спецификацию для всех используемых варинтов шаблона. Вроде
    using my_template<int>;
    Ответ написан
    6 комментариев
  • Какая функция (или набор разных ф-ий) изменения "мощности" цвета света при распространении луча?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Это называется яркость света. Цвет лазера особо не меняется. Наверно, можно считать, что яркость уменьшается очень медленно линейно из-за рассеивания воздухом. Для не лазерных источников света яркость убывает квадратично от расстояния.
    Ответ написан
  • How to fix packing error in ue5?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Try doing what the error messages are telling you:

    Detected compiler newer than Visual Studio 2022, please update min version checking in WindowsPlatformCompilerSetup.h


    Or install the Visual Studio 2022 instead of what you have.
    Ответ написан
  • Почему в c++ еще нету Null-Conditional Operator?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Это не достаточно частая операция в С++, чтобы срочно надо было вводить новый оператор в синтаксис. Комитет занят более интересными вещами на годы вперед.
    Ответ написан
    3 комментария
  • На чём создать прогу для обработки больших данных?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    100gb - это не так и много. Даже не надо кластера, чтобы это обрабатывать.

    Быстрее, конечно, работать будет на C++/rust каком-нибудь, но обработка csv может быть легче реализованна на питоне.
    Ответ написан