• Как передать counter is for loop внутрь макроса?

    @Ariox41
    Обычно используется примерно такое решение:
    #include <iostream>
    
    #define CHECK_EQ(a, b) \
      do{ \
      if ((a) != (b)){    \
        std::cout << "Values are not equal: \"" << a << "\" != \"" << b << "\"" << std::endl \
        << "\tleft expression: \"" << #a << "\"\n\tright expression: \"" << #b << "\""  << std::endl  \
        << "\tin \"" << __FILE__ << ":" << __LINE__ << "\"" <<std::endl; \
      } \
      }while(0)
     // while(0) для того, чтобы поставить ; после макроса.
     
    int main()
    {
      int a = 1;
      for(int i = 0; i < 3; ++i){
          CHECK_EQ(a + 1, i);
      }
    }


    Вывод:
    Values are not equal: "2" != "0"
    	left expression: "a + 1"
    	right expression: "i"
    	in "<...>:17"
    Values are not equal: "2" != "1"
    	left expression: "a + 1"
    	right expression: "i"
    	in "<...>:17"
    Ответ написан
    Комментировать
  • Актуально ли сейчас метапрограммирование на С++?

    @Ariox41
    Если вы про метопрограммирование шаблонов, то да - актуально. Более того, комитет по стандартизации прикладывает некоторые усилия для того, чтобы метопрограммирование в c++ стало проще для понимания и использования, т.к. это в конечном итоге позволяет повысить качество кода. В стандартной библиотеке сейчас на самом деле довольно часто прямо или косвенно используется метопрограммирование, например, при формировании условий для SFINAE, или для таких вещей, как `std::bind` и `std::variant`. Конечно, на практике обычно достаточно того, что уже есть в библиотеках, но не всегда.

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

    Если вы всё же хотите изучать метопрограммирование, для начала рекомендую ознакомится с этой статьёй: Simple C++11 metaprogramming, а далее изучать boost::hana (т.к. там довольно хорошая документация).
    Ответ написан
    Комментировать
  • Как создать глобальный объект для всех элементов проекта?

    @Ariox41
    Вообще, вам стоит почитать про синглтоны в C++, но если лень, самый безопасный вариант - синглтон Майерса:
    #include <string>
    
    // Синглтон Майерса. Переменная str будет создана один раз при первом вызове getPrefix, начиная с c++11 это ещё и потокобезопастно.
    const std::string& getPrefix(){ 
        static std::string str  {"pref::"}; // Инициализация должна быть в конструкторе. 
        return str;
    }
    
    // Его использование.
    std::string addPrefix(const std::string& str){
        return getPrefix() + str; 
    }
    Ответ написан
    Комментировать
  • Что за ошибка с Boost.Asio?

    @Ariox41
    Для вывода сообщения в нормальном виде попробуйте выполнить команду chcp 1251 перед запуском программы. Или можно в реестре поменять кодировку по умолчанию, как тут сделано.

    По поводу самой ошибки: в Windows порты по умолчанию разделены на две группы, работа с которыми требует разных прав (на самом деле там всё сложнее, но я подробностей не помню). Попробуйте увеличить номер порта, что-то вроде 51501. Ну или с правами администратора запустите для проверки. Возможно, у вас проблема не в этом, но я с таким сталкивался.

    EDIT: Если не получится с кодировками, выведите номер ошибки и ищите по нему, boost это позволяет сделать. Ну и напомню, что для работы клиента нужно сначала запустить сервер, а то мало ли.
    Ответ написан
    3 комментария
  • Как исправить ошибку линкера?

    @Ariox41
    Компоновщик не видит деструктора, потому что он не реализован.
    Просто оберните все указатели в std::unique_ptr, деструкттор сгенерируется автоматически, да и других проблем поубавится.
    class ModuleClass
    {
    public:
      ModuleClass(const char* ModuleGUID);
      ModuleClass(std::string ModuleGUID);
    
      std::string GetModuleGUID();
      int ProcessTast(TaskClass t);
    
      ~ModuleClass() = default; // генерируется автоматически благодаря умным указателям
    private:
    
      int Start(TaskClass t);
      int Stop();
      int Extract();
      int SetExec();
      int Launch();
    
      int AnswersProcessor();
      int ReadingThreadChecker();
    
      std::string ModuleGUID;
      std::atomic<bool> isStarted;
      std::atomic<bool> stopFlag;
      std::unique_ptr<PipeServerClass> pipe;
      std::unique_ptr<MessageCollectorClass> msgCollector;
      std::unique_ptr<std::thread> AnswerProcessingThread;
      std::unique_ptr<std::thread> ReaderCheckingThread;
    };


    UPD:
    Хотя с потоками могут возникнуть проблемы, нужно либо дождаться их завершения, либо вызвать detach. В любом случае, нужно либо использовать пользовательский deleter для unique_ptr, либо реализовать специальную обертку над потоком.
    Ответ написан
  • Как подключить библиотеку boost для Android в Qt?

    @Ariox41
    Под android не работал, но судя по всему строка
    LIBS += C:/qt_projects/-----X-----/boost/1.59.0/libs
    лишняя.

    Возможно, ниже нужно писать что-то вроде
    contains(ANDROID_TARGET_ARCH,x86) {
        ANDROID_EXTRA_LIBS += \
            L"C:/qt_projects/-----X-----/boost/1.59.0/libs/x86/gnu-5/" \
            lboost_atomic \
            lboost_chrono \
            ..........
    }
    по аналогии со стандартным для qmake добавлением в LIBS (Lпуть - путь к каталогу с либами, lназвание - название библиотеки без lib и .so)

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

    И да, boost и Qt отлично друг с другом уживаются.
    Ответ написан
  • Как динамически подключать библиотеки?

    @Ariox41
    Посмотрите в сторону boost::DLL

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

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

    Пример из документации, на всякий случай:
    // my_plugin_api.hpp
    #include <string>
    
    class my_plugin_api {
    public:
       virtual std::string name() const = 0;
       virtual float calculate(float x, float y) = 0;
    
       virtual ~my_plugin_api() {}
    };

    Реализация плагина:
    // my_plugin_sum.cpp
    #include <boost/config.hpp> // for BOOST_SYMBOL_EXPORT
    #include "../tutorial_common/my_plugin_api.hpp"
    
    namespace my_namespace {
    
    class my_plugin_sum : public my_plugin_api {
    public:
        my_plugin_sum() {
            std::cout << "Constructing my_plugin_sum" << std::endl;
        }
    
        std::string name() const {
            return "sum";
        }
    
        float calculate(float x, float y) {
            return x + y;
        }
    
        ~my_plugin_sum() {
            std::cout << "Destructing my_plugin_sum ;o)" << std::endl;
        }
    };
    
    // Exporting `my_namespace::plugin` variable with alias name `plugin`
    // (Has the same effect as `BOOST_DLL_ALIAS(my_namespace::plugin, plugin)`)
    extern "C" BOOST_SYMBOL_EXPORT my_plugin_sum plugin;
    my_plugin_sum plugin;
    
    } // namespace my_namespace

    Собственно, загрузка библиотеки:
    #include <boost/dll/import.hpp> // for import_alias
    #include <iostream>
    #include "../tutorial_common/my_plugin_api.hpp"
    
    namespace dll = boost::dll;
    
    int main(int argc, char* argv[]) {
    
        boost::filesystem::path lib_path(argv[1]);          // argv[1] contains path to directory with our plugin library
        boost::shared_ptr<my_plugin_api> plugin;            // variable to hold a pointer to plugin variable
        std::cout << "Loading the plugin" << std::endl;
    
        plugin = dll::import<my_plugin_api>(          // type of imported symbol is located between `<` and `>`
            lib_path / "my_plugin_sum",                     // path to the library and library name
            "plugin",                                       // name of the symbol to import
            dll::load_mode::append_decorations              // makes `libmy_plugin_sum.so` or `my_plugin_sum.dll` from `my_plugin_sum`
        );
    
        std::cout << "plugin->calculate(1.5, 1.5) call:  " << plugin->calculate(1.5, 1.5) << std::endl;
    }

    Вывод:
    Loading the plugin
    Constructing my_plugin_sum
    plugin->calculate(1.5, 1.5) call:  3
    Destructing my_plugin_sum ;o)
    Ответ написан
    Комментировать
  • Почему IDE не отображает информацию о некоторых типах?

    @Ariox41
    В C++11 добавились некоторые синтаксические изменения, в результате чего все IDE некоторое время неправильно интерпретировали некоторые конструкции. На данный момент ситуация улучшилась, но не везде. Рекомендую обратить внимание на IDE, которые используют clang code model. Я тестировал только QtCreator, там с этим есть некоторые проблемы, но работать можно. Да и собственная модель кода без clang в последних версиях неплохо работает.
    Ответ написан
    Комментировать
  • Какую литературу по изучению С(не С++) и IDE посоветуете и почему С++ популярней С?

    @Ariox41
    По поводу того, что лучше, есть множество холиваров, и с обоих сторон приводятся как конструктивные утверждения в пользу языка, так сомнительные. По факту, отношение языкам часто основывается на окружении и субъективном мнении. Сейчас довольно часто высказывается мнение, что вокруг C++ сформировалось множество необоснованных мифов, связанных в основном с тем, что многие C++ программисты на самом деле используют так называемый 'C с классами' (даже вакансия такая встречается - C/C++).
    У меня сложилось следующее мнение о C++:
    + RAII позволяет безопасно управлять ресурсами (в первую очередь, обеспечить их освобождение)
    + Механизм исключений существенно облегчает написание кода, если им не злоупотреблять
    + Мощная система типов позволяет отлавливать многие ошибки во время компиляции и переиспользовать код. При этом часто можно разрабатывать абстракции с минимальной стоимостью (времени выполнения)
    + Большая часть С является подмножеством C++, что позволяет писать программы на C с использованием только тех частей C++, которые действительно полезны. Особенно полезно при написании программ для микроконтроллеров, где ограничена память, может быть запрещено её динамическое выделение, или может отсутствовать стандартная библиотека.
    + В С++ хорошая стандартная библиотека, хотя и не без недостатков.

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

    По поводу IDE: на мой взгляд, самой удобной сейчас является QtCreator, на втором месте - KDevelop. Под windows многие любят использовать Visual Studio, мне в неё не нравится долгая установка и столь же долгое удаление, да и сама среда не отличается производительностью (по сравнению с QtCreator, а так существует множество менее производительных IDE). С Eclipse у меня отношения не сложились.

    Литературу для начинающих посоветовать не могу. Наиболее полезные ресурсы по языку - en.cppreference.com (или ru.cppreference.com, но там меньше) и www.cplusplus.com
    Ответ написан
  • Проблемы с компиляцией в visual studio 2015, после адаптации с visual studio 2010. Что делать?

    @Ariox41
    std::array создается на стеке как обычный сишный массив и требует указания размера во время компиляции, примерно так: std::array<int, 3> array = {1, 2, 3};

    Edit: Возможно, там нужен не std::array, а что-то другое, но где-то использован using namespace std
    Edit: Не сразу въехал во вторую часть. Шаблонный параметр должен быть известен во время компиляции, т.е. bmp->Width должен быть constexpr или statc constexpr с соответствующим синтаксисом обращения. Динамические массивы в С++ - это std::vector, у вас скорее всего использовался array из CLI, но в CLI я не разбираюсь.
    Ответ написан
    1 комментарий
  • Созданный проект не запускается на других компьютерах. Что делать?

    @Ariox41
    Судя по всему, вы компилируете 64-разрядный *.exe, который не может запуститься на 32-разрядной системе. Соответственно, нужно компилировать 32-разрядный, покопайтесь в настройках проекта.
    Если это не так, предоставленной информации недостаточно (какая хоть ошибка возникает?).
    Ответ написан
    7 комментариев
  • Как создать проинициализированное статическое поле?

    @Ariox41
    Самый простой и надежный вариант - Синглтон Майерса:
    std::vector<std::string>& getStaticMyVector (){
       static std::vector<std::string> staticVector = {"", ""};
       return v;
    }

    Дальше в любой функции можно получить статический вектор, вызвав getStaticMyVector ().

    Если инициализация более сложная, можно сделать примерно так:
    std::vector<std::string>& getStaticMyVector (){
       auto init = []{
         std::vector<std::string> v;
         v.push_back(" ");
         return v;
       };
       static std::vector<std::string> staticVector = init();
       return v;
    }
    Ответ написан
    Комментировать
  • Что нужно прочитать чтобы начать писать программы на С++?

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

    Если интересует программирование на C++ в принципе, читайте Майерса. Начать стоит с этой книги. Возможно, с первого раза не все будет понятно, но она задаст направление дальнейшего развития. Затем стоит почитать "Эффективный и современный С++: 42 рекомендации по использованию C++11 и C++14" - там уже про современные стандарты языка.
    Ответ написан
    Комментировать
  • Где можно взять побольше материала по теме "Функции для работы с динамической памятью в C++"?

    @Ariox41
    Вам нужны именно функции, или всё же подходы к работе с динамической памятью?
    Если функции, то рекомендую погуглить перегрузку операторов new и delete, и их различных вариаций (в частности, placement new и non-throwing new), ну и сишные malloc, realloc, free.
    Варианты new и связанные с ним функции можно посмотреть тут.

    Если подходы, то добавляются еще как минимум умные указатели и аллокаторы.
    Ответ написан
    Комментировать
  • Как правильно очистить память при работе со стеком (ADT)?

    @Ariox41
    Рекомендую почитать про std::unique_ptr
    Вот вариант на c++11
    #include <memory>
    
    template<typename T>
    class Stack{
    public:
      Stack(std::size_t maxSize_): maxSize(maxSize_){}
    
      // Что происходит, когда стек пуст? Можно бросить исключение, или сделать как в std
      T pop(){
        // if (!tmp) throw ...
        auto tmp = std::move(head);
        // Обратите внимание, теперь head пуст
        head = std::move(tmp->next);
        // Теперь tmp->next пуст
        --size;
        return tmp->value;
      }
    
      bool push(T value){
        if (size+1 > maxSize)
          return false;
    
        // здесь может быть брошено исключение из-за нехватки памяти
        std::unique_ptr<Node> tmp(new Node(value));
    
        tmp->next = std::move(head);
        head = std::move(tmp);
        ++size;
        return true;
      }
    
    private:
      struct Node{
        T value;
        std::unique_ptr<Node> next = nullptr;
        Node(T value_) noexcept
          : value(value_)
        { }
      };
    
      std::unique_ptr<Node> head = nullptr;
      std::size_t maxSize;
      std::size_t size = 0;
    };
    Ответ написан
    Комментировать
  • Нужно ли изучать автоматизацию сборки?

    @Ariox41
    IDE пока что довольно плохо поддерживают cmake, но ситуация меняется к лучшему. В любом случае не получится использовать его, совсем не зная, разве что для простых случаев.
    Что касается преимуществ: основное преимущество cmake в том, что он умеет самостоятельно подставлять флаги для нужного компилятора и умеет искать популярные библиотеки, если заданы соответствующие переменные среды. Последние версии умеют работать с header-only библиотеками. Кроме того, в его составе есть утилиты CPack и CTest. Про CPack ничего сказать не могу, но CTest довольно удобен для тестирования, и его можно сочетать gtest и аналогами.
    И я бы не стал пытаться самостоятельно написать make файл для кросплатформенного приложения/библиотеки с тестами и внешними зависимостями, у cmake это лучше получится.
    Ответ написан
    Комментировать
  • В чем ошибка в операторе присвоения?

    @Ariox41
    В строке MP3_Format mp3a = "Summertime"; происходит инициализация, а не присваивание.
    Код
    MP3_Format mp3a{};
    mp3a = "Summertime";
    должен работать нормально.
    Но лучше отдельно реализовать конструктор для const char* и оператор присваивания, как в ответе Mercury13
    Ответ написан
    Комментировать