На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Как исправить ошибку: "LNK2019 ссылка на неразрешенный внешний символ"?
    Здравствауте!
    Подскажите, пожалуйста, из-за чего эта ошибка и как ее исправить?:

    Ошибка LNK2019 ссылка на неразрешенный внешний символ __imp__invalid_parameter в функции "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl std::operator+<char,struct std::char_traits<char>,class std::allocator<char> >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &&,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &&)" (??$?HDU?$char_traits@D@std@@V?$allocator@D@1@@std@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@$$QEAV10@0@Z). school D:\Programming\VS\source\repos\school\school\school.obj 1

    ExpandedWrap disabled
      #include <iostream>
      #include <memory>
      #include <mysql_driver.h>
      #include <mysql_connection.h>
      #include <cppconn/driver.h>
      #include <cppconn/exception.h>
      #include <cppconn/resultset.h>
      #include <cppconn/statement.h>
      #include <cppconn/prepared_statement.h>
       
      //using namespace std;
       
      class MySQLConnection {
      private:
          std::unique_ptr<sql::Connection> connection;
       
      public:
          MySQLConnection(const std::string& host, int port,
              const std::string& user, const std::string& password,
              const std::string& database) {
       
              sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();
              std::string connectionString = "tcp://" + host + ":" + std::to_string(port);
       
              connection.reset(driver->connect(connectionString, user, password));
              connection->setSchema(database);
          }
       
          void executeQuery(const std::string& query) {
              std::unique_ptr<sql::Statement> stmt(connection->createStatement());
              std::unique_ptr<sql::ResultSet> res(stmt->executeQuery(query));
       
              while (res->next()) {
                  // Обработка результатов
                  std::cout << "Результат: " << res->getString(1) << std::endl;
              }
          }
       
          bool isConnected() {
              return connection.get() != nullptr && !connection->isClosed();
          }
      };
       
      int main() {
          try {
              MySQLConnection db(
                  "your_remote_server_ip",
                  3306,
                  "your_username",
                  "your_password",
                  "your_database"
              );
       
              if (db.isConnected()) {
                  std::cout << "Подключение установлено успешно!" << std::endl;
                  db.executeQuery("SELECT VERSION()");
              }
       
          }
          catch (sql::SQLException& e) {
              std::cerr << "MySQL Error: " << e.what() << std::endl;
          }
       
          return 0;
      }
    Сообщение отредактировано: DDim1000 -
      Если у кого-то есть желание, посмотрите проект: https://disk.yandex.ru/d/1Jpu8d2JXhMkgw
        DDim1000, привет!

        От всей души тебя благодарю за "вчерашний кроссворд" :lol: Дело все в том, что за свою 35-летнюю практику программирования я сегодня 1-й раз запустил компиляцию программы на С++ с помощью компилятора от Microsoft. Всё это "мелкомягкое" проходило мимо меня. Сперва совсем другие языки программирования: Turbo Pascal, потом Delphi, потом за злобу дня Virtual Pascal, потом Free Pascal. А потом вообще ударился в "экзотику" - REXX от OS/2, MEX от системы Maximus BBS, Clarion for DOS, потом Windows. Потом пришёл к Borland C++ Builder'у. Но и тут настигло разочарование!!! В языке программирования С++ есть Стандарт (потом они появятся и в других), и его нельзя членососить!!! А Borland это делал не стесняясь. Поэтому я ушел. Увидел в фрэймворке Qt дружественный интерфейс, и завязанный на Стандарт, и завязанный, как бонус, ещё и на кроссплатформенность.

        Вот такая получилась Преамбула. "А почему с Майкрософтом почти дел не имел всё это время?" - возникает резонный вопрос. Отвечу честно: не знаю! Какое-то внутреннее отвращение. Но буквально месяц назад я для себя решил. Надо перебороть себя, поставить студию, и попробовать ее в действии. Даже если блевать тянет.

        И ТАК

        Моя "первичная" установка "Microsoft Visual Studio Enterprise 2022" не встала как надо, я её нахрен снёс, даже стандартных заголовков типа math.h не видела. Мать-её-перемать, удалил и поставил "Microsoft Visual Studio Community 2022". И вот тут стало уже интереснее:

        1) Стандартное консольное приложение "Хэлоу ворлд!" заработало
        2) Я скопировал код твой проги "сканнар". Понятное дело, даже на первом этапе в редакторе не виделись заголовки, но стало ещё интереснее

        СЕКРЕТНЫЙ СЕКРЕТ
        Скрытый текст
        А он заключается в том, что все пути твоего проекта - не соответствуют путям моего проекта в данном ответе. И с этим нужно смириться, но извлечь из этого полезную инфу как-то надо. Уверяю - надо!
        Просто нужно заценить аналогию и внести правки в свой проект. Это как два байта об асфальт, ну или одно из двух?


        РЕШАЕМ

        1) Прописываем "пути заголовок в MySQL" в опциях проекта. Т.е. добавляем: "Свойства->Каталоги С++->Включаемые каталоги путь. В моём случае "E:\Documents\3.Projects\C++\TestMySQL\mysql\include\jdbc"
        2) Прописываем "пути либ MySQL" в опциях проекта. Т.е. добавляем: "Свойства->Каталоги С++->Каталоги библиотек. В моём случае "E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14
        3) Прописываем конкретные добавляемые либы. Тут опять, понятное дело, у тебя свое размещение, у меня - своё. Поэтому - ориентируйся! "Свойства->Компоновщик->Все параметры->Дополнительные зависимости"

        У меня получилось прописать дополнительно:
        • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\libcrypto.lib
        • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\libssl.lib
        • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconn.lib
        • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconn-static.lib
        • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconnx.lib
        • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconnx-static.lib
        После всего сказанного - проект (солюшен) собрался успешно.

        В ОБЩЕМ

        В общем - была проблема сборки (линкинга). Не добавили и не указали нужные либы и их пути для сборки как должно.
          ExpandedWrap disabled
            template <typename Ch, typename Tr, typename Al>
            std::basic_string<Ch, Tr, Al> operator+(std::basic_string<Ch, Tr, Al>&&, std::basic_string<Ch, Tr, Al>&&);
          является сугубо Стандартным, никакого к SQL отношения не имеющим. Имя __imp__invalid_parameter является импортируемым входом из библиотеки импорта для DLL, в которой лежит реализация стандартной RTL от Майкрософта. Исходное имя _invalid_parameter является функцией, задействованной в отладочной сборке RTL, через которую сообщается о тех или иных багах в коде, которые обнаруживаются в runtime. Обычно это всякоразные нарушения Стандарта, которые невозможно определить при компиляции и Стандартом описываемые как "undefined behavior" и "no diagnostic is required", например, использование инвалидированного итератора. У меня бага, обнаруживаемая этим оператором в его отладочной форме, выглядит вот так:
          Прикреплённая картинка
          Прикреплённая картинка

          Она сообщает, что когда оба параметра оператора являются rvalue ref, реализация вправе считать, что они оба уникальны и не могут совпадать. И это логично, т.к. rvalue ref формально являются временными объектами и получить более одной ссылки на один и тот же временный объект невозможно иначе, как спецом написать кривой код. Я этого добился, явно переместив lvalue с помощью std::move() дважды в одном выражении, в итоге попробовав сконкатенировать некую строку со строкой, которая хранит невесть что.
          Как бы там ни было, в релизе _invalid_parameter() не используется. Вообще ничего отладочного не используется, что конечно не означает, что баг в программе сам собой вылечивается. Почему линкер не нашёл этого символа, ябеспонятия. Первое, что приходит в голову – отсутствие #include <string>, что само по себе является ошибкой, ведущей к undefined behavior. Но не исключено, что это баг мэйкера проекта, который не добавил нужную DLL. Точнее, либу импорта к ней. Я бы попробовал отключить динамическую RTL и использовать статическую. Если баг линковки исчезнет, то это баг сборки самой динамической RTL, и об этом нужно сообщить в саппорт Студии
          Сообщение отредактировано: Qraizer -
            Цитата Majestio @
            DDim1000, привет!

            От всей души тебя благодарю за "вчерашний кроссворд" :lol: Дело все в том, что за свою 35-летнюю практику программирования я сегодня 1-й раз запустил компиляцию программы на С++ с помощью компилятора от Microsoft. Всё это "мелкомягкое" проходило мимо меня. Сперва совсем другие языки программирования: Turbo Pascal, потом Delphi, потом за злобу дня Virtual Pascal, потом Free Pascal. А потом вообще ударился в "экзотику" - REXX от OS/2, MEX от системы Maximus BBS, Clarion for DOS, потом Windows. Потом пришёл к Borland C++ Builder'у. Но и тут настигло разочарование!!! В языке программирования С++ есть Стандарт (потом они появятся и в других), и его нельзя членососить!!! А Borland это делал не стесняясь. Поэтому я ушел. Увидел в фрэймворке Qt дружественный интерфейс, и завязанный на Стандарт, и завязанный, как бонус, ещё и на кроссплатформенность.

            Вот такая получилась Преамбула. "А почему с Майкрософтом почти дел не имел всё это время?" - возникает резонный вопрос. Отвечу честно: не знаю! Какое-то внутреннее отвращение. Но буквально месяц назад я для себя решил. Надо перебороть себя, поставить студию, и попробовать ее в действии. Даже если блевать тянет.

            И ТАК

            Моя "первичная" установка "Microsoft Visual Studio Enterprise 2022" не встала как надо, я её нахрен снёс, даже стандартных заголовков типа math.h не видела. Мать-её-перемать, удалил и поставил "Microsoft Visual Studio Community 2022". И вот тут стало уже интереснее:

            1) Стандартное консольное приложение "Хэлоу ворлд!" заработало
            2) Я скопировал код твой проги "сканнар". Понятное дело, даже на первом этапе в редакторе не виделись заголовки, но стало ещё интереснее

            СЕКРЕТНЫЙ СЕКРЕТ
            Скрытый текст
            А он заключается в том, что все пути твоего проекта - не соответствуют путям моего проекта в данном ответе. И с этим нужно смириться, но извлечь из этого полезную инфу как-то надо. Уверяю - надо!
            Просто нужно заценить аналогию и внести правки в свой проект. Это как два байта об асфальт, ну или одно из двух?


            РЕШАЕМ

            1) Прописываем "пути заголовок в MySQL" в опциях проекта. Т.е. добавляем: "Свойства->Каталоги С++->Включаемые каталоги путь. В моём случае "E:\Documents\3.Projects\C++\TestMySQL\mysql\include\jdbc"
            2) Прописываем "пути либ MySQL" в опциях проекта. Т.е. добавляем: "Свойства->Каталоги С++->Каталоги библиотек. В моём случае "E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14
            3) Прописываем конкретные добавляемые либы. Тут опять, понятное дело, у тебя свое размещение, у меня - своё. Поэтому - ориентируйся! "Свойства->Компоновщик->Все параметры->Дополнительные зависимости"

            У меня получилось прописать дополнительно:
            • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\libcrypto.lib
            • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\libssl.lib
            • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconn.lib
            • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconn-static.lib
            • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconnx.lib
            • E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconnx-static.lib
            После всего сказанного - проект (солюшен) собрался успешно.

            В ОБЩЕМ

            В общем - была проблема сборки (линкинга). Не добавили и не указали нужные либы и их пути для сборки как должно.

            Majestio, большое, большое спасибо!!!
            Я 2 дня седел на разных форумах, но никто не мог толком ничего подсказать. А ты разобрался, и все так четко объяснил!
            Сообщение отредактировано: DDim1000 -
              Проект компилируеться, но возникла еще одна ошибка.
              При выполнении программы выскакивает сообщение:


              Не удается продолжить выполнение кода, поскольку система не обноружила mysqlcppconn-10-vs14.dll. Для устранеия этой пролемы попробуйте переустанвить программу.

              Но когда я прописыва путь к mysqlcppconn-10-vs14.dll, при сборки проета выходит ошибка:
              Ошибка LNK1107 недопустимый или поврежденный файл: не удается прочитать по 0x388 school D:\Programming\VS\source\repos\school\school\MySQL\lib64\mysqlcppconn-10-vs14.dll


              Подскажите, пожалуста, как исправить ошибку?
              Прикреплённая картинка
              Прикреплённая картинка


              P.S.
              Как здесь изображения прикреплять?
                Цитата DDim1000 @
                Не удается продолжить выполнение кода, поскольку система не обноружила mysqlcppconn-10-vs14.dll. Для устранеия этой пролемы попробуйте переустанвить программу.

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

                1. Или положить нужные .dll рядом с исполняемым .exe файлом
                2. Или нужные .dll записать в C:\Windows\System32

                Я бы посоветовал первый способ. А вообще лучше глянь страничку на моём сайте, и сам реши для себя как тебе лучше.
                  Цитата DDim1000 @
                  Majestio, большое, большое спасибо!!!
                  Я 2 дня седел на разных форумах, но никто не мог толком ничего подсказать. А ты разобрался, и все так четко объяснил!

                  Это супер! Хорошо, что ты пришёл на наш форум. Оставайся тут, сделай закладочку в своём браузере на наш форум. Через месяц-два это уже будет не "наш" а "твой" форум. Да, конечно "трафик общения" тут не большой. Но, уверяю тебя, тут очень много интересных и толковых людей!

                  Хотя ... о чём я ;) Ты с нами уже с 2019 года. Просто не пропадай.
                    Теперь такая ошибка:

                    Debug Error!

                    Program: D:\Programming\VS\source\repos\school\x64\Debug\school.exe

                    abort() has been called

                    (Press Retry to debug the application)

                    Прикреплённая картинка
                    Прикреплённая картинка
                      Ну тут уже проще, явная ошибка в коде твоей программы. Самый простой вариант ее найти - пошаговое исполнение в отладчике. Кода у тебя там мало, найдешь достаточно быстро.
                        Ошибка происходит вот на эти строках:

                        ExpandedWrap disabled
                                  connection.reset(driver->connect(connectionString, user, password));
                                  connection->setSchema(database);


                        Вот видео: https://rutube.ru/video/private/4a2d373fed2...P7X9cVc0_Tu7uZw
                          Очень подозреваю, что SQL собрана версией Студии, отличной от твоей. Попытка сконструировать SQLString где-то изнутри DLL наталкивается на совершенно дикие значения размеров памяти, типа 435626798759 байт. Что очень похоже на нарушение ODR.
                          Думаю, нужно либо выяснить, какой версией собирались твои DLLки и использовать ту же, либо пересобрать самому из сырцов.

                          Добавлено
                          Но возможно, что причина в другом. Всё-таки
                          ExpandedWrap disabled
                                KernelBase.dll!RaiseException() Нет данных
                                vcruntime140.dll!_CxxThrowException(void * pExceptionObject, const _s__ThrowInfo * pThrowInfo) Строка 80C++
                                mysqlcppconn-10-vs14.dll!__scrt_throw_std_bad_alloc() Строка 35C++
                            >   mysqlcppconn-10-vs14.dll!operator new(unsigned __int64 size) Строка 48C++
                                [Внедренный фрейм] mysqlcppconn-10-vs14.dll!std::_Default_allocate_traits::_Allocate(const unsigned __int64) Строка 79C++
                                mysqlcppconn-10-vs14.dll!std::_Allocate_manually_vector_aligned<std::_Default_allocate_traits>(const unsigned __int64 _Bytes) Строка 134C++
                                [Внедренный фрейм] mysqlcppconn-10-vs14.dll!std::_Allocate(const unsigned __int64) Строка 229C++
                                [Внедренный фрейм] mysqlcppconn-10-vs14.dll!std::allocator<char>::allocate(const unsigned __int64 _Count) Строка 801C++
                                [Внедренный фрейм] mysqlcppconn-10-vs14.dll!std::string::_Construct_lv_contents(const std::string &) Строка 2908C++
                                mysqlcppconn-10-vs14.dll!std::string::basic_string<char,std::char_traits<char>,std::allocator<char>>(const std::string & _Right) Строка 2420C++
                                [Внедренный фрейм] mysqlcppconn-10-vs14.dll!sql::SQLString::{ctor}(const sql::SQLString &) Строка 66C++
                                [Внедренный фрейм] mysqlcppconn-10-vs14.dll!sql::Variant::{ctor}(const sql::SQLString &) Строка 277C++
                                mysqlcppconn-10-vs14.dll!sql::mysql::MySQL_Connection::MySQL_Connection(sql::Driver * _driver, sql::mysql::NativeAPI::NativeConnectionWrapper & _proxy, const sql::SQLString & hostName, const sql::SQLString & userName, const sql::SQLString & password) Строка 162C++
                                mysqlcppconn-10-vs14.dll!sql::mysql::MySQL_Driver::connect(const sql::SQLString & hostName, const sql::SQLString & userName, const sql::SQLString & password) Строка 130C++
                                school.exe!MySQLConnection::MySQLConnection(const std::string & host, int port, const std::string & user, const std::string & password, const std::string & database) Строка 26C++
                                school.exe!main() Строка 47C++
                                school.exe!invoke_main() Строка 79C++
                                school.exe!__scrt_common_main_seh() Строка 288C++
                                school.exe!__scrt_common_main() Строка 331C++
                                school.exe!mainCRTStartup(void * __formal) Строка 17C++
                                kernel32.dll!BaseThreadInitThunk()  Нет данных
                                ntdll.dll!RtlUserThreadStart()  Нет данных
                          и всё, что выше school.exe!MySQLConnection::MySQLConnection, без исходных текстов.
                            Цитата Qraizer @
                            Очень подозреваю, что SQL собрана версией Студии, отличной от твоей. ...

                            Что это значит? Версия библиотеки не та?
                              Ну... наверное. Косвенно это также ещё следует из названия "mysqlcppconn-10-vs14.dll", что скорее всего «но это неточно©» означает сборку на 14-ой версии RTL. Нынешняя ВизуалСтудия2022 имеет 17-ую версию.

                              Добавлено
                              Технически пересобрать не должно быть неподъёмным процессом. Весь мир опенсорса так работает. На пересборке пререквизитов в конечной точке, в смысле. Но нынче MySQL под Oracle-ом, а его отношение к опенсорс довольно невнятное.

                              Добавлено
                              Ещё есть мысль: попробовать отключить отладочную RTL и заюзать релизную вместо. Кстати, вполне может помочь, т.к. отладочная реализация 100пудово отличается от релизной, откуда и может следовать нарушение ODR. Т.е. SQL собрана с релизной RTL, а твоё приложение с отладочной, и это и есть источник проблемы.

                              Добавлено
                              P.S. Просто переключи Конфигурацию решения в Release:
                              ExpandedWrap disabled
                                MySQL Error: Unable to connect to your_remote_server_ip:3306
                                Когда я переключаю на Release, то сразу вот эти строки подсвечиваются красной чертой. То есть библиотеки становятся не достуаны.

                                #include <mysql_driver.h>
                                #include <mysql_connection.h>
                                #include <cppconn/driver.h>
                                #include <cppconn/exception.h>
                                #include <cppconn/resultset.h>
                                #include <cppconn/statement.h>
                                #include <cppconn/prepared_statement.h>
                                Сообщение отредактировано: DDim1000 -
                                  Вероятно, когда ты правил проект по заветам Majestio, ты отредактировал только одну, текущую конфигурацию. Надо было бы все, чтоб не возвращаться к этому, но ничего страшного, просто повтори ещё раз.
                                    Кстати во избежании будущих проблем с переносом проекта на другой диск или папку рекомендую использовать не абсолютные, а относительные пути до этих библиотек и заголовочных путей в настройках проекта (раз уж они внутри проекта) и использовать макросы подстановки $(SolutionDir) $(ProjectDir) и т.д.
                                    $(SolutionDir)MySQL\lib64\vs14

                                    Добавлено
                                    Далее..
                                    Почему вы линкуете mysqlcppconnx-static.lib? У вас же динамическая линковка, а не статическая. Должно быть mysqlcppconnx.lib вернее mysqlcppconn.lib (потому что используете именно mysqlcppconn-10-vs14.dll, а не mysqlcppconnx-2-vs14.dll)

                                    Ну и после исправлений тестовый пример работает нормально.

                                    P.S. 14 это не версия студии, а версия toolchain (так написано в доке с MySQL connector). так что нарушений ODR быть не должно. 22 студия так же использует 14 тулчейн (v14.3), так что все работает и на новых студиях
                                    Сообщение отредактировано: sharky72 -
                                      И в Debug билде надо убрать STATIC_CONCPP в настройках препроцессора. Раз уж решили работать именно с dll.
                                      Сообщение отредактировано: sharky72 -
                                        Цитата sharky72 @
                                        P.S. 14 это не версия студии, а версия toolchain (так написано в доке с MySQL connector). так что нарушений ODR быть не должно. 22 студия так же использует 14 тулчейн (v14.3), так что все работает и на новых студиях
                                        Никогда не задумывался, что это действительно можно тоже назвать тулчейном, как принято в embedded. Но отсутствие нарушений ODR всё ж не факт. Счас вот глянул, у меня их две версии, 14.16.27023 и 14.44.35207, отличаются минорами, ибо апдейты Студии они такие. Понятно, что первая уже неактуальна и не используется, но минор версии, на которой был собран SQL, неизвестно какой, и даже если в пределах мажора 14 ничего не должно поменяться, поменяться-таки могло, т.к. баги совместимости никто не отменял. Поэтому я всегда после наката нового апдейта рабочие проекты собираю rebuild all. Так, на всякий случай.

                                        Добавлено
                                        Но тут всё проще: приложение собирается DEBUG, т.е. с отладочной версией RTL, а SQL был собран с релизной версией. По-хорошему надо где-то там взять отладочную SQL и в дебажные конфигурации своих проектов втыкать их.
                                          Цитата Majestio @
                                          У меня получилось прописать дополнительно:
                                          E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\libcrypto.lib
                                          E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\libssl.lib
                                          E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconn.lib
                                          E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconn-static.lib
                                          E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconnx.lib
                                          E:\Documents\3.Projects\C++\TestMySQL\mysql\lib64\vs14\mysqlcppconnx-static.lib

                                          Вот тут я написал неправильно! :wall: Т.к. линкеру нужно под каждую конфигурацию указывать нужные либы по строгим правилам. Для статических - статические, для динамических - динамические. В дополнение - для релизных - релизные, для отладочных - отладочные. Все скопоп прописывать низя, скорее всего будут конфликты символов. Сорян! :whistle:

                                          Ах, да, еще ... где-то в "глубоких водах" GNU я вроде встречал такой термин как "гибридная" или "смешанная" линковка. Это когда часть либ линкуется статически, а часть динамически. ChatGPT утверждает, что и Мелкософтовские линкеры тоже владеют таким кунг-фу. Думаю, тоже стоит внимание обратить на эту шляпу. А то мало ли ...

                                          Добавлено
                                          Цитата Qraizer @
                                          Никогда не задумывался, что это действительно можно тоже назвать тулчейном, как принято в embedded.

                                          Это пробел в знаниях. Несущественный, но всё же. В embedded это принято ровно на столько, на сколько принято в не embedded. Ибо термин toolchain (инструментальная цепочка) не привязан исключительно к embedded-системам, а имеет более общий смысл в разработке программного обеспечения. Тулчейн - это набор инструментов, используемых для создания исполняемых файлов, библиотек или других артефактов для определённой целевой платформы (таргета). Он включает в себя компиляторы, ассемблеры, компоновщики (линкеры), отладчики и другие утилиты, необходимые для сборки и, возможно, отладки кода.
                                            Кстати. С понятием 'toolchain' я столкнулся уже достаточно давно, в районе 2011 года, когда познакомился с проектом MXE. Но именно "кристальное" его воплощение я заметил в языке программирования Rust. Увы и ах, этот язык мне не зашел ввиду слишком узкого диапазона применений. К примеру, лепить GUI-морды сегодня на базе GTK2, когда уже есть GTK4 - считаю просто кощунственным. И тем не менее, заглянул в структуру каталогов когда-то установленного Раста, я наблюдаю:

                                            ExpandedWrap disabled
                                              X:\Tools\Rust\rust\toolchains
                                               ├─ stable-i686-pc-windows-gnu
                                               ├─ stable-i686-pc-windows-msvc
                                               ├─ stable-x86_64-pc-windows-gnu
                                               └─ stable-x86_64-pc-windows-msvc

                                            Правда прекрасно? :lol:
                                              Цитата Qraizer @


                                              Нет. Проект отлично собирается в DEBUG c релизной dll (pdb есть, функции в стеке посмотреть можно). И работает. В исходном vcxproj для debug конфигурации указана статическая конфигурация в переменных препроцессора для подключения mysqlconnector. Плюс указана неправильная либа для статической линковки, хотя сам проект собирается как /MDd (Multithreaded debug DLL). Короче там в конфигурации каша. Если все указать правильно то ошибок и эксепшнов не возникает. На 2022 студии.
                                              Ну и настройки релизной конфигурации вобще отсутствует.

                                              В любом случае можно скачать и отладочную версию. на dev.mysql.com/downloads/connector/cpp
                                              Сообщение отредактировано: sharky72 -
                                                У меня возник вопрос: может я вообще делаю ни так? В общем, у меня есть задача: нужно подключиться к базе данных котора находиться на веб-хостинге. Дак, у меня правильная логика программы, или нет?
                                                  Цитата DDim1000 @
                                                  Дак, у меня правильная логика программы, или нет?

                                                  Вроде бы и правильная ;) но положа честную руку на горячее сердце - боюсь соврать. С Дазами Банных я обычно работал только средствами Qt. Предлагаю тебе воспользоваться "антисанкциями", выкачать и установить себе SQL-клиент Navicat. А вот уже в нём настрой нужный коннект, "увидь" таблицы, и только потом тестируй свою прогу. А то может случиться ситуация что просто проблемсы с БД. Не ленись - проверь!
                                                    Цитата DDim1000 @
                                                    У меня возник вопрос: может я вообще делаю ни так? В общем, у меня есть задача: нужно подключиться к базе данных котора находиться на веб-хостинге. Дак, у меня правильная логика программы, или нет?

                                                    В смысле работы с Mysql? Ну да. Создали коннектор. Задали строку соединения и логин/пароль. Вызвали метод соединения, обработали исключение в случае ошибки.
                                                    Только я бы все таки не стал вызывать соединение из конструктора. Можно, но некрасиво из за того что там бросаются исключения в случае ошибок и isConnected() в данном случае не нужен ;)

                                                    P.S. Я до сих пор использую dbForge Studio for MySql 9 (2020) пока она была бесплатной для некоммерческого использования
                                                      Цитата Majestio @
                                                      Это пробел в знаниях. Несущественный, но всё же. В embedded это принято ровно на столько, на сколько принято в не embedded.
                                                      Почему пробел. Я в курсе. Просто почему-то до этого не задумывался, что версии RTL можно так называть.
                                                      Цитата sharky72 @
                                                      Нет. Проект отлично собирается в DEBUG c релизной dll (pdb есть, функции в стеке посмотреть можно). И работает.
                                                      Не нет, а да. В проекте используются подставляемые функции (inline которые) с внешним связыванием (external linkage), и по Стандарту они обязаны (не ограничиваясь):
                                                      • иметь определение в каждой единице трансляции, в которых используются;
                                                      • в каждой единице трансляции, в которых используются, объявляться как подставляемые с внешним связыванием (с точностью до разрешения перегрузки);
                                                      • все такие определения должны быть выполнены одинаковой последовательностью токенов.
                                                      и неважно, как именно единицы трансляции линкуются в результирующее приложение, посредством статической линковки или динамической. Если конкретно у тебя смешение inline с внешним связыванием — обсуждаемый operator+() является non-static function template, что ставит его в один ряд с inline — работает, то лишь потому, что ожидаемое поведение является частным случаем неопределённого. Вот у нас с ТС, к примеру, не работает. И в отладчике легко видно, почему: в итоге где-то изнутри mysqlcppconn-10-vs14.dll управление попадает в sqlstring.h, конкретно в конструктор SQLString, и контент его параметра const std::string & other не совпадает с определением std::string в приложении, т.б. разные последовательности токенов на лицо. Почему так? Та потому, что линкеру приспичило обработать внешние имена в объектных файлах и библиотеках вот в каком-то таком порядке. И pdb тут совершенно ни причём, на линковку он никак не влияет. Как раз наоборот, создаётся в процессе линковки. Так-то он лишь предоставляет информацию для отладчика, и при нарушении ODR способен даже запутать, т.к. отладчик может в сырцах показывать совсем не то, что в исполняемом коде.
                                                        Не буду спорить. В любом случае решение есть. На сайте есть дебажная версия dll и lib. Правильней будет использовать их в отладочном билде. Решается так же прописыванием путей к нужной либе.
                                                        По крайней мере я проверил на своем mysql. Код работает. Единственное пришлось еще доложить папку plugins

                                                        Добавлено
                                                        Ну и чтобы не тащить все это в проект, и облегчить настройку подключения mysqlconnector автору рекомендую посмотреть в сторону vcpkg.
                                                        Сообщение отредактировано: sharky72 -
                                                          Цитата Qraizer @
                                                          Почему пробел. Я в курсе. Просто почему-то до этого не задумывался, что версии RTL можно так называть.

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

                                                          Цитата Qraizer @
                                                          что версии RTL можно так называть

                                                          Вот тут ты не прав - тулчейны, это не просто разные RTL, это полные разные инфраструктуры сопутствующих инструментариев.

                                                          И более того! Вспомни многообразие форматов исполняемых файлов - это связка "операционная система +архитектура". И не известно кто тут главный, а кто ведомый. Хотя "архитектура" конечно главнее по факту, т.к. она определяет его бинарный код, его внутренности. Но не факт. Тут сложно сказать, сложно что определить, что более первично - "сосуд" или его "содержимое" :-?
                                                            Цитата Majestio @
                                                            Варишься в твоих в своих мелкософтах и свету белого не видишь.
                                                            :D Тебе что, назвать количество разных процессоров, с которыми работал и работаю? Из них только около половины используют GNU той или иной разновидности. И ОСей в них нет, там сплошной freestanding
                                                              Цитата Qraizer @
                                                              Тебе что, назвать количество разных процессоров, с которыми работал и работаю? Из них только около половины используют GNU той или иной разновидности. И ОСей в них нет, там сплошной freestanding

                                                              Ага, вот ты и попался! :lol: Варишься в твоих в своих мелкософтах и эмбедах всяких, и свету белого не видишь! :lol:
                                                                :popcorn:
                                                                  Цитата Majestio @
                                                                  Цитата DDim1000 @
                                                                  Дак, у меня правильная логика программы, или нет?

                                                                  Вроде бы и правильная ;) но положа честную руку на горячее сердце - боюсь соврать. С Дазами Банных я обычно работал только средствами Qt. Предлагаю тебе воспользоваться "антисанкциями", выкачать и установить себе SQL-клиент Navicat. А вот уже в нём настрой нужный коннект, "увидь" таблицы, и только потом тестируй свою прогу. А то может случиться ситуация что просто проблемсы с БД. Не ленись - проверь!

                                                                  Качнул и установил Navicat, и вот что он говорит при попытки подключиться к БД: "1130 - Host '169...' is not allowed to connect to this MySQL server". То есть, получатся, что, сам сервер не разрешает подключиться?
                                                                  Сообщение отредактировано: DDim1000 -
                                                                    Цитата DDim1000 @
                                                                    То есть, получатся, что, сам сервер не разрешает подключиться?

                                                                    Ну да, получается что так. Поработай с настройками сервера, постарайся получить коннект с помощью Navicat. И только после этого возвращайся к кодированию.
                                                                      Кстати ... если у тебя проблемсы с MySQL-сервером, а они явно у тебя есть - рекомендую тебе просто ужасно-прекрасную софтину Open Server. Да, сия софтина обычно используется для web-разработок. Тем не менее, в её составе есть полноценные версии MySQL и PostgreSQL, практически готовые сразу после установки. Очень очень рекомендую. Сам пользую уже лет 10, и вааще доволен.
                                                                        Цитата DDim1000 @
                                                                        1130 - Host '169...' is not allowed to connect to this MySQL server

                                                                        1. Смотри есть ли права доступа у данного пользователя на подключение к конкретному хосту или к любому (в таблице mysql.user). Если нет - то дай права через grant all priveleges
                                                                        2. Проверь что mysql забинден на нужный интерфейс. Или слушает все. в bind-address = 0.0.0.0
                                                                          Цитата sharky72 @
                                                                          Цитата DDim1000 @
                                                                          У меня возник вопрос: может я вообще делаю ни так? В общем, у меня есть задача: нужно подключиться к базе данных котора находиться на веб-хостинге. Дак, у меня правильная логика программы, или нет?

                                                                          В смысле работы с Mysql? Ну да. Создали коннектор. Задали строку соединения и логин/пароль. Вызвали метод соединения, обработали исключение в случае ошибки.
                                                                          Только я бы все таки не стал вызывать соединение из конструктора. Можно, но некрасиво из за того что там бросаются исключения в случае ошибок и isConnected() в данном случае не нужен ;)

                                                                          P.S. Я до сих пор использую dbForge Studio for MySql 9 (2020) пока она была бесплатной для некоммерческого использования

                                                                          Установил локальный сервер, установил Navicat Premium, создал БД. Но мая программа не может подключиться к базе данны, пишет: MySQL Error: Unable to connect to HчЇФи:3306

                                                                          Что можно сделать?

                                                                          ExpandedWrap disabled
                                                                            #include <iostream>
                                                                            #include <memory>
                                                                            #include <mysql_driver.h>
                                                                            #include <mysql_connection.h>
                                                                            #include <cppconn/driver.h>
                                                                            #include <cppconn/exception.h>
                                                                            #include <cppconn/resultset.h>
                                                                            #include <cppconn/statement.h>
                                                                            #include <cppconn/prepared_statement.h>
                                                                             
                                                                            //using namespace std;
                                                                             
                                                                            class MySQLConnection {
                                                                            private:
                                                                                std::unique_ptr<sql::Connection> connection;
                                                                             
                                                                            public:
                                                                                MySQLConnection(const std::string& host, int port,
                                                                                    const std::string& user, const std::string& password,
                                                                                    const std::string& database) {
                                                                             
                                                                                    sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();
                                                                                    std::string connectionString = "tcp://" + host + ":" + std::to_string(port);
                                                                             
                                                                                    connection.reset(driver->connect(connectionString, user, password));
                                                                                    connection->setSchema(database);
                                                                                }
                                                                             
                                                                                void executeQuery(const std::string& query) {
                                                                                    std::unique_ptr<sql::Statement> stmt(connection->createStatement());
                                                                                    std::unique_ptr<sql::ResultSet> res(stmt->executeQuery(query));
                                                                             
                                                                                    while (res->next()) {
                                                                                        // Обработка результатов
                                                                                        std::cout << "Результат: " << res->getString(1) << std::endl;
                                                                                    }
                                                                                }
                                                                             
                                                                                bool isConnected() {
                                                                                    return connection.get() != nullptr && !connection->isClosed();
                                                                                }
                                                                            };
                                                                             
                                                                            int main() {
                                                                                setlocale(LC_ALL, "Russian");
                                                                             
                                                                                try {
                                                                                    MySQLConnection db(
                                                                                        "locolhost", // host
                                                                                        3306,
                                                                                        "root", // your_username
                                                                                        "", // your_password
                                                                                        "school" // your_database
                                                                                    );
                                                                             
                                                                                    if (db.isConnected()) {
                                                                                        std::cout << "Подключение установлено успешно!" << std::endl;
                                                                                        db.executeQuery("SELECT VERSION()");
                                                                                    }
                                                                             
                                                                                }
                                                                                catch (sql::SQLException& e) {
                                                                                    std::cerr << "MySQL Error: " << e.what() << std::endl;
                                                                                }
                                                                             
                                                                                return 0;
                                                                            }
                                                                            Самое простое попробуйте. Наберите в браузере http://HчЇФи:3306 и посмотрите на ответ. Если сервер работает по этому адресу, тогда вы увидите ошибку в протоколе рукопожатия в браузере, а если нет -- страницу: нет доступа.

                                                                            В зависимости от этого и надо будет решать проблему.

                                                                            1) Ошибка в браузере есть т.е. сервер работает и отвечает. Тогда надо смотреть на то, чтобы отправляет ему коннектор.
                                                                            2) Ошибка в браузере, что нет сервера. Тогда проверяем настройки у mysql. Обычно там стоит строго 127.0.0.1:3306 и к нему не подключиться даже через v6
                                                                              Цитата macomics @
                                                                              Самое простое попробуйте. Наберите в браузере http://HчЇФи:3306 и посмотрите на ответ. Если сервер работает по этому адресу, тогда вы увидите ошибку в протоколе рукопожатия в браузере, а если нет -- страницу: нет доступа.

                                                                              В зависимости от этого и надо будет решать проблему.

                                                                              1) Ошибка в браузере есть т.е. сервер работает и отвечает. Тогда надо смотреть на то, чтобы отправляет ему коннектор.
                                                                              2) Ошибка в браузере, что нет сервера. Тогда проверяем настройки у mysql. Обычно там стоит строго 127.0.0.1:3306 и к нему не подключиться даже через v6

                                                                              Сообщние в браузере:

                                                                              Не удается получить доступ к сайту
                                                                              Проверьте, нет ли опечаток в имени хоста xn--h-ptb9al4f.

                                                                              Если все правильно, воспользуйтесь инструментом "Диагностика сетей Windows".
                                                                              DNS_PROBE_FINISHED_NXDOMAIN
                                                                              Сообщение отредактировано: DDim1000 -
                                                                                А вы все сделали как вам советовали?
                                                                                1. Как сказал Qraizer запустить в релизе
                                                                                2. Как советовал я - поставить отладочную версию mysql сonnector и запустить в дебаге. Ибо похоже дебаг проект и релиз dll у вас не дружат.
                                                                                3. "locolhost" это что-то жутко интересное... ;) Интересно будет узнать что это.

                                                                                ЗЫ. QTешников не спрашивали ;) Они вообще не в зуб ногой в кроме своего фреймворка ;)
                                                                                Сообщение отредактировано: sharky72 -
                                                                                  Цитата DDim1000 @
                                                                                  Проверьте, нет ли опечаток в имени хоста xn--h-ptb9al4f.

                                                                                  Это означает, что по внешнему ip порт не доступен (2 вариант). Значит проверяйте настройки сервера mysql. Скорее всего, к нему можно подключиться строго через 127.0.0.1:3306

                                                                                  Добавлено
                                                                                  Хотя надо еще попробовать локальный ip компьютера вместо dns
                                                                                  Сообщение отредактировано: macomics -
                                                                                    Цитата sharky72 @
                                                                                    А вы все сделали как вам советовали?
                                                                                    1. Как сказал Qraizer запустить в релизе
                                                                                    2. Как советовал я - поставить отладочную версию mysql сonnector и запустить в дебаге. Ибо похоже дебаг проект и релиз dll у вас не дружат.
                                                                                    3. "locolhost" это что-то жутко интересное... ;) Интересно будет узнать что это.

                                                                                    ЗЫ. QTешников не спрашивали ;) Они вообще не в зуб ногой в кроме своего фреймворка ;)

                                                                                    Когда я преключаю на Release, сразу появляются куча ошибок.

                                                                                    https://disk.yandex.ru/i/JL2VqnRFCuZPYA
                                                                                    Сообщение отредактировано: DDim1000 -
                                                                                      Цитата macomics @
                                                                                      Хотя надо еще попробовать локальный ip компьютера вместо dns
                                                                                      К слову: 127.0.0.1 отнюдь не то же самое, что локальный IP.
                                                                                        Цитата sharky72 @
                                                                                        ЗЫ. QTешников не спрашивали Они вообще не в зуб ногой в кроме своего фреймворка

                                                                                        user posted image
                                                                                          Цитата Qraizer @
                                                                                          К слову: 127.0.0.1 отнюдь не то же самое, что локальный IP.

                                                                                          Именно потому, что это разные адреса я про это и сказал. Доступ по dns может отсутствовать из-за недоступности локального ip за роутером. Но вот если и с локальным ip будет тот же ответ, тогда значит, что mysql слушает только 127.0.0.1 (localhost, но только по v4).
                                                                                            А вот через Комадную строку все работает.

                                                                                            ExpandedWrap disabled
                                                                                              Microsoft Windows [Version 10.0.19045.6332]
                                                                                              (c) Корпорация Майкрософт (Microsoft Corporation). Все права защищены.
                                                                                               
                                                                                              C:\Windows\system32>D:
                                                                                               
                                                                                              D:\>cd Programming\Servers\xampp\mysql\bin
                                                                                               
                                                                                              D:\Programming\Servers\xampp\mysql\bin>mysql.exe -h localhost --port=3306 -u root --password
                                                                                              Enter password:
                                                                                              Welcome to the MariaDB monitor.  Commands end with ; or \g.
                                                                                              Your MariaDB connection id is 9
                                                                                              Server version: 10.4.32-MariaDB mariadb.org binary distribution
                                                                                               
                                                                                              Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
                                                                                               
                                                                                              Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
                                                                                               
                                                                                              MariaDB [(none)]> SELECT NOW();
                                                                                              +---------------------+
                                                                                              | NOW()               |
                                                                                              +---------------------+
                                                                                              | 2025-09-28 20:11:06 |
                                                                                              +---------------------+
                                                                                              1 row in set (0.000 sec)
                                                                                               
                                                                                              MariaDB [(none)]>
                                                                                              Ну так вы же через командную строку используете localhost, а не dns или ip вашей сетевой на компьютере. Вот и проверяйте подключение к серверу по тем же параметрам в программе или через браузер, как я показал ранее.
                                                                                                Цитата DDim1000 @
                                                                                                Цитата sharky72 @
                                                                                                А вы все сделали как вам советовали?

                                                                                                Когда я преключаю на Release, сразу появляются куча ошибок.

                                                                                                https://disk.yandex.ru/i/JL2VqnRFCuZPYA

                                                                                                Ну вам же Qraizer написал что для Release так же НУЖНО настроить пути и библиотеки
                                                                                                Сообщение отредактировано: sharky72 -
                                                                                                  Переключил на Release, теперь такая ошибка:

                                                                                                  ExpandedWrap disabled
                                                                                                    MySQL Error: Authentication plugin 'mysql_native_password' cannot be loaded: Не найден указанный модуль.
                                                                                                     
                                                                                                     
                                                                                                    D:\Programming\VS\source\repos\school\x64\Release\school.exe (процесс 7780) завершил работу с кодом 0 (0x0).
                                                                                                    Нажмите любую клавишу, чтобы закрыть это окно:


                                                                                                  Скопировал файл mysql_native_password.dll в папку с exe-файлом, но ошибка осталась.
                                                                                                  Сообщение отредактировано: DDim1000 -
                                                                                                    надо было скопировать полностью папку plugin. Он ищет именно в папке.
                                                                                                    Почему так - надо спрашивать у разрабов MySQL connector

                                                                                                    ЗЫ. Qraizer таки был прав использовть релизную dll для дебага нельзя. Посыпаю голову пеплом.

                                                                                                    https://dev.mysql.com/doc/dev/connector-cpp...test/usage.html
                                                                                                    On Windows it is not possible to mix code built in release and debug modes.

                                                                                                    И там же по поводу папки plugin (можно решить через переменную среды). В общем в доках все есть. Нужно только их прочитать.

                                                                                                    MySQL client library plugins
                                                                                                    The classic API is implemented using the MySQL client library which might need to load plugins during some operations (mainly during authentication). In case of system-wide installation the required plugins (and their dependencies) should be also installed system-wide and available at the default location where the client library looks for them.

                                                                                                    If however Connector/C++ was installed to a local directory the plugins (and their dependencies) are installed together with the connector at ${mysql-concpp_DIR}/lib64/plugins but the client library will not know how to find them. To fix this pass their location as PLUGIN_DIR connection option that is recognized by the classic API.

                                                                                                    Note
                                                                                                    Client library plugins must be installed and PLUGIN_DIR must be correctly set (if needed) on the target host on which the application is run. This might be different from the environment in which application was built. Note that client library plugins are loaded dynamically at run-time and they are not required during build process.
                                                                                                    Client library plugins can have further dependencies. For example authentication_kerberos_client plugin depends on Kerberos libraries and when used these libraries must be found on the target system.
                                                                                                    If client library plugins are not available the connector will still work correctly provided that it does not invoke any functionality that requires these plugins. For example if the server to which it connects does not have any accounts that use advanced authentication mechanisms that would require use of client library authentication plugins.
                                                                                                    In case of a local installation the mysql-concpp module sets the MYSQL_CONCPP_PLUGIN_DIR variable to the location where bundled client library plugins (and their dependencies) are located inside connector installation directory. Depending on the deployment strategy this information can be used, for example, to bundle the available plugins with the final application. In case of system-wide installation the plugins are not bundled with the connector and MYSQL_CONCPP_PLUGIN_DIR variable is not set.
                                                                                                    Сообщение отредактировано: sharky72 -
                                                                                                      Заработало!!!
                                                                                                      Большое спасибо за помощь!

                                                                                                      ExpandedWrap disabled
                                                                                                        Подключение установлено успешно!
                                                                                                        Результат: 10.4.32-MariaDB
                                                                                                      Сообщение отредактировано: DDim1000 -
                                                                                                        Здравствуйте!
                                                                                                        Возник вопрос: как сделать, чтобы русcкие буквы отображались корректно?
                                                                                                        ExpandedWrap disabled
                                                                                                          Подключение установлено успешно!
                                                                                                          |1|Р"РчР?РёС?|
                                                                                                          |2|Р>С'Р?С?|
                                                                                                        Сообщение отредактировано: DDim1000 -
                                                                                                          Цитата DDim1000 @
                                                                                                          Возник вопрос: как сделать, чтобы русcкие буквы отображались корректно?

                                                                                                          Лучший вариант (но я еще сам не пробовал) - использовать ConEmu в качестве терминала, настроенным на UTF-8 по умолчанию + в студии использовать расширение ConEmu Integration 2017. Подчёркиваю, я сам этим пока не пользовался, но интересно, и я скоро сам попробую. В этом большой бонус - полноценный терминал с UTF-8 кодировкой.

                                                                                                          Второй вариант - писать свою функцию преобразования перед печатью на стандартный терминал со стандартной кодировкой cp866. Должно получиться что-то типа:

                                                                                                          ExpandedWrap disabled
                                                                                                            #include <string>
                                                                                                            #include <iostream>
                                                                                                            #include <windows.h>
                                                                                                             
                                                                                                            std::string utf8_to_cp866(const std::string& utf8_str) {
                                                                                                                // 1. UTF-8 -> UTF-16
                                                                                                                int wide_size = MultiByteToWideChar(CP_UTF8, 0, utf8_str.c_str(), -1, nullptr, 0);
                                                                                                                std::wstring wide_str(wide_size, 0);
                                                                                                                MultiByteToWideChar(CP_UTF8, 0, utf8_str.c_str(), -1, &wide_str[0], wide_size);
                                                                                                             
                                                                                                                // 2. UTF-16 -> cp866
                                                                                                                int cp866_size = WideCharToMultiByte(866, 0, wide_str.c_str(), -1, nullptr, 0, nullptr, nullptr);
                                                                                                                std::string cp866_str(cp866_size, 0);
                                                                                                                WideCharToMultiByte(866, 0, wide_str.c_str(), -1, &cp866_str[0], cp866_size, nullptr, nullptr);
                                                                                                             
                                                                                                                return cp866_str;
                                                                                                            }
                                                                                                             
                                                                                                            int main() {
                                                                                                                std::string utf8_str = u8"Привет, ворлд!";
                                                                                                                std::string cp866_str = utf8_to_cp866(utf8_str);
                                                                                                                std::cout << cp866_str << std::endl;
                                                                                                                return 0;
                                                                                                            }

                                                                                                          С кириллицей должно прокатить. Но, сам понимаешь, символы юникода, которым нет соответствия в cp866, выведены не будут.
                                                                                                            Цитата Majestio @
                                                                                                            Второй вариант - писать свою функцию преобразования перед печатью на стандартный терминал со стандартной кодировкой cp866. Должно получиться что-то типа:

                                                                                                            Третий вариант. Использовать WSL или вовсе перейти на Linux. Там давно уже UTF8 и нету этих приколов.
                                                                                                              Четвертый вариант. Использовать либу boost ;)

                                                                                                              ExpandedWrap disabled
                                                                                                                #include <boost/locale.hpp>
                                                                                                                #include <string>
                                                                                                                #include <iostream>
                                                                                                                 
                                                                                                                int main() {
                                                                                                                    std::string utf8_str = u8"Привет, васьминогам!";
                                                                                                                    std::cout << boost::locale::conv::from_utf(utf8_str, "CP866") << std::endl;
                                                                                                                    return 0;
                                                                                                                }
                                                                                                                Команда в консоли "chcp 65001", програмно SetConsoleOutputCP(), конкретно в Плюсах std::locale(). Проще свои сырцы уже представлять компилятору к нужной кодировке. И нужен соответствующий шрифт, естественно.
                                                                                                                Только вот вопрос: а тебе этот UTF-8 вообще зачем? Многобайтная кодировка – это жестокая боль, что б тебе не советовали из никсов.
                                                                                                                  Цитата Qraizer @
                                                                                                                  Команда в консоли "chcp 65001", програмно SetConsoleOutputCP(), конкретно в Плюсах std::locale().

                                                                                                                  Qraizer, вот скажи, зачем ты так издеваешься над человеком этим своим советом? >:(

                                                                                                                  С каких это пор виндовая стандартная консоль дружила с многобайтовыми кодировками? Не, ну серьёзно. Ну покажи код, как в наш век гомоглобальной экзистенции модуляции синтеза, на примере вывода UTF-8 строк, сделать печать прямым выводом, без перекодировки в cp866 и вывести юникод в эту всратую консоль, чисто одной сменой локали...

                                                                                                                  Цитата Qraizer @
                                                                                                                  Проще свои сырцы уже представлять компилятору к нужной кодировке.

                                                                                                                  Дело не в одних сырцах. Есть ещё и данные из БД MySQL, которые туда нужно вписать, и оттуда ещё и читать. И я тебе, как родному, скажу: лучше это будет, если таблицы будут там созданы в кодировке utf8mb4 вместе с современными правилами сортировки ("collation" — так это называется на языке западных кровавых империалистов) utf8mb4_unicode_520_ci. Вот тогда, и именно тогда, и только тогда — никакая внешняя индустриальная интервенция (особенно китайская) нам не страшна!!! Вот именно тогда мы будем готовы кодить в жёстком стиле, по всем фронтам, но соблюдая современные международные нормы. Свободу восьминогам! :victory:
                                                                                                                    ExpandedWrap disabled
                                                                                                                      #include <iostream>
                                                                                                                      #include <string>
                                                                                                                      #include <locale>
                                                                                                                       
                                                                                                                      int main()
                                                                                                                      {
                                                                                                                        std::string str = u8"Хеллоу, уорлд!";
                                                                                                                        std::locale locRusUTF8("russian.utf8");
                                                                                                                       
                                                                                                                        std::cout.imbue(locRusUTF8);
                                                                                                                        std::cout << str << std::endl;
                                                                                                                      }


                                                                                                                    ExpandedWrap disabled
                                                                                                                      D:\Work\DelMe>chcp 65001
                                                                                                                      Active code page: 65001
                                                                                                                       
                                                                                                                      D:\Work\DelMe>delMe.exe
                                                                                                                      Хеллоу, уорлд!
                                                                                                                       
                                                                                                                      D:\Work\DelMe>


                                                                                                                    Добавлено
                                                                                                                    UTF-8 вам в одну руку и флаг в другую, уважаемые уважатели суррогатных байт. А я вот не люблю, когда не могу сделать
                                                                                                                    ExpandedWrap disabled
                                                                                                                      std::replace(str.begin(), str.end(), u8'л', u8'l');

                                                                                                                    когда str.length() возвращает 25 вместо правильного 14 и тем более когда str[6] вместо u8',' возвращает мне некое '\xD0'
                                                                                                                    Сообщение отредактировано: Qraizer -
                                                                                                                      Просто ты не распознал всей вкусности юникода!
                                                                                                                      Да, пришли времена когда печатаемый символ может/должен занимать более одного байта. Смирись с этим, или проиграешь!!! ;)
                                                                                                                        И есчо ... што-то тут не все гладко, я не поленился и затестил в студии:
                                                                                                                        Прикреплённая картинка
                                                                                                                        Прикреплённая картинка

                                                                                                                        Модификатор u8 есть, но такое ощущение нас рать, и что идет вывод win1251->cp866
                                                                                                                          Подскажите, пожалуйста, почему ошибка?:
                                                                                                                          это объявление не содержит класс хранения или спецификатор типа. Ст. 15.
                                                                                                                          На 15 ст. находится вызов функции system("chcp 65001");.
                                                                                                                          ExpandedWrap disabled
                                                                                                                            #include "MySQLConnection.h"
                                                                                                                            #include <cstdlib>   // system()
                                                                                                                            #include <iostream>
                                                                                                                            #include <memory>
                                                                                                                            #include <mysql_driver.h>
                                                                                                                            #include <mysql_connection.h>
                                                                                                                            #include <cppconn/driver.h>
                                                                                                                            #include <cppconn/exception.h>
                                                                                                                            #include <cppconn/resultset.h>
                                                                                                                            #include <cppconn/statement.h>
                                                                                                                            #include <cppconn/prepared_statement.h>
                                                                                                                             
                                                                                                                            namespace school
                                                                                                                            {    
                                                                                                                                system("chcp 65001");
                                                                                                                                MySQLConnection::MySQLConnection(const std::string& host, int port,
                                                                                                                                    const std::string& user, const std::string& password,
                                                                                                                                    const std::string& database) {
                                                                                                                             
                                                                                                                                    sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();
                                                                                                                                    std::string connectionString = "tcp://" + host + ":" + std::to_string(port);
                                                                                                                             
                                                                                                                                    connection.reset(driver->connect(connectionString, user, password));
                                                                                                                             
                                                                                                                                    // Настройка кодировки UTF-8
                                                                                                                                    std::unique_ptr<sql::Statement> stmt(connection->createStatement());
                                                                                                                                    stmt->execute("SET NAMES 'utf8'");
                                                                                                                                    stmt->execute("SET CHARACTER SET utf8");
                                                                                                                             
                                                                                                                                    connection->setSchema(database);
                                                                                                                                }
                                                                                                                             
                                                                                                                                void MySQLConnection::executeQuery(const std::string& query) {
                                                                                                                                    std::unique_ptr<sql::Statement> stmt(connection->createStatement());
                                                                                                                                    std::unique_ptr<sql::ResultSet> res(stmt->executeQuery(query));
                                                                                                                             
                                                                                                                                    while (res->next()) {
                                                                                                                                        // Обработка результатов
                                                                                                                                        std::cout << "Результат: " << res->getString(1) << std::endl;
                                                                                                                                    }
                                                                                                                                }
                                                                                                                             
                                                                                                                                bool MySQLConnection::isConnected() {
                                                                                                                                    return connection.get() != nullptr && !connection->isClosed();
                                                                                                                                }
                                                                                                                            }
                                                                                                                          Сообщение отредактировано: DDim1000 -
                                                                                                                            Цитата DDim1000 @


                                                                                                                            Вы вкрячили непонятно что внутри namespace. Это и ни объявление функции, ни её реализация. Поэтому компилятор вас и не понял.
                                                                                                                            system() или SetConsoleOutputCP() надо вызывать в main(). В добавок system() вам выдаст "мусор" в консоль "Active codepage xxxx", потому что это запуск команды cmd. Тогда уж system("chcp 65001 >nul").
                                                                                                                            Сообщение отредактировано: sharky72 -
                                                                                                                              Цитата Majestio @
                                                                                                                              Просто ты не распознал всей вкусности юникода!
                                                                                                                              Ещё как вкусил. Главная проблема юникода не в много...символьности (UTF-16 тоже имеет суррогатные пары). Главная его проблема в том, что вместо того, чтобы разобраться с зоопарком мультикультурности и устранить связанные с ним неудобства, он его стандартизировал и т.с. эти неудобства узаконил.
                                                                                                                              Цитата Majestio @
                                                                                                                              Да, пришли времена когда печатаемый символ может/должен занимать более одного байта
                                                                                                                              Их никогда и не было. Но люди умели писать код в многобайтных кодировках. Проблема не в самой многобайтовости, а в отсутствии абстракции "символ". Это уже не к юникоду, конечно, а к std. Если уж ввели char8_t, префикс u8 и класс std::u8string, почему они по-прежнему отражают абстракцию "байт"?
                                                                                                                              Мне несложно написать свои алгоритмы и функции для "символов" и таскать их из проекта в проект. Более того, в C++11 сделали некий шаг в эту сторону, предоставив фасеты и классы. Пусть шаг и неудобный, т.к. отделён от самой абстракции "символ", но вот прошло 6 лет, а воз не то что и ныне там, а этот шаг в принципе отменён, и ничего не предоставлено взамен. Причём формулировка причины, типа, "ой, мы ниасилили сделать это безопасно с точки зрения обработки апшибков" и "ай-яй-яй, эти фасеты локале-независимы, поэтому им нечего делать в <locale>". Оттакъот. Юникоду 35 лет, к слову, и <locale> появился аж в C++98, в первой редакции Стандарта.
                                                                                                                              Сообщение отредактировано: Qraizer -
                                                                                                                                Цитата DDim1000 @
                                                                                                                                ExpandedWrap disabled
                                                                                                                                      system("chcp 65001");
                                                                                                                                Не надо system(). Я ж упомянул программное средство:
                                                                                                                                ExpandedWrap disabled
                                                                                                                                  SetConsoleOutputCP(65001);
                                                                                                                                  Здравствуйте!
                                                                                                                                  У меня снова возникла ошибка: "ссылка на неразрешенный внешний символ", другом проекте.
                                                                                                                                  ссылка на неразрешенный внешний символ "public: void __cdecl school::TabTest::run(void)" (?run@TabTest@school@@QEAAXXZ) в функции main.
                                                                                                                                  Еще такая ошибка:
                                                                                                                                  неразрешенных внешних элементов: 1

                                                                                                                                  h-file:
                                                                                                                                  ExpandedWrap disabled
                                                                                                                                    #pragma once
                                                                                                                                     
                                                                                                                                    #include <iostream>
                                                                                                                                    #include <sstream>
                                                                                                                                    #include <string>
                                                                                                                                    #include <vector>
                                                                                                                                    #include <locale>
                                                                                                                                     
                                                                                                                                    namespace school {
                                                                                                                                     
                                                                                                                                        // Класс-обертка для преобразования в строку
                                                                                                                                        class StringConverter
                                                                                                                                        {
                                                                                                                                        public:
                                                                                                                                            template<typename T>
                                                                                                                                            static std::wstring toString(T val);
                                                                                                                                        };
                                                                                                                                     
                                                                                                                                        // Класс для работы со строками
                                                                                                                                        class MyString : public std::wstring
                                                                                                                                        {
                                                                                                                                        public:
                                                                                                                                            MyString();
                                                                                                                                            MyString(std::wstring s);
                                                                                                                                            MyString(const wchar_t* s);
                                                                                                                                     
                                                                                                                                            MyString& operator=(const std::wstring& a);
                                                                                                                                     
                                                                                                                                            template<typename T>
                                                                                                                                            MyString& operator=(const T a);
                                                                                                                                        };
                                                                                                                                     
                                                                                                                                        // Класс для работы с вектором
                                                                                                                                        template<typename T>
                                                                                                                                        class MyVector : public std::vector<T>
                                                                                                                                        {
                                                                                                                                        public:
                                                                                                                                            T& operator[](const size_t i);
                                                                                                                                            void resize(size_t new_size, const T& value = T());
                                                                                                                                        };
                                                                                                                                     
                                                                                                                                        // Класс для форматирования таблицы
                                                                                                                                        class TableFormatter
                                                                                                                                        {
                                                                                                                                        private:
                                                                                                                                            MyVector<MyVector<MyString>>& m;
                                                                                                                                            MyVector<MyString>& h;
                                                                                                                                            size_t& CMAX;
                                                                                                                                     
                                                                                                                                        public:
                                                                                                                                            TableFormatter(size_t& cmax,
                                                                                                                                                MyVector<MyVector<MyString>>& data,
                                                                                                                                                MyVector<MyString>& header);
                                                                                                                                     
                                                                                                                                            void format();
                                                                                                                                     
                                                                                                                                        private:
                                                                                                                                            void calculateMaxColumns();
                                                                                                                                            void resizeRows();
                                                                                                                                            void addRowNumbers();
                                                                                                                                            void calculateColumnWidths();
                                                                                                                                            void alignColumns();
                                                                                                                                            void alignHeaders();
                                                                                                                                        };
                                                                                                                                     
                                                                                                                                        // Класс для вывода таблицы
                                                                                                                                        class TablePrinter
                                                                                                                                        {
                                                                                                                                        private:
                                                                                                                                            MyVector<MyVector<MyString>>& m;
                                                                                                                                            MyVector<MyString>& h;
                                                                                                                                            size_t& CMAX;
                                                                                                                                     
                                                                                                                                        public:
                                                                                                                                            TablePrinter(
                                                                                                                                                size_t& cmax,
                                                                                                                                                MyVector<MyVector<MyString>>& data,
                                                                                                                                                MyVector<MyString>& header);
                                                                                                                                     
                                                                                                                                            void print(std::wostream& o);
                                                                                                                                     
                                                                                                                                        private:
                                                                                                                                            std::wstring createLine();
                                                                                                                                            void printHeader(std::wostream& o);
                                                                                                                                            void printRows(std::wostream& o);
                                                                                                                                        };
                                                                                                                                     
                                                                                                                                        // Основной класс таблицы
                                                                                                                                        class Tab
                                                                                                                                        {
                                                                                                                                        private:
                                                                                                                                            MyVector<MyVector<MyString>> m;
                                                                                                                                            MyVector<MyString> h;
                                                                                                                                            size_t CMAX = 0;
                                                                                                                                     
                                                                                                                                        public:
                                                                                                                                            Tab();
                                                                                                                                     
                                                                                                                                            MyVector<MyString>& operator[](const size_t i);
                                                                                                                                     
                                                                                                                                            template<typename ... T>
                                                                                                                                            void head(T ... t);
                                                                                                                                            void formater();
                                                                                                                                     
                                                                                                                                            friend std::wostream& operator<<(std::wostream& o, Tab& t);
                                                                                                                                        };
                                                                                                                                     
                                                                                                                                        // Объявление дружественной функции
                                                                                                                                        std::wostream& operator<<(std::wostream& o, Tab& t);
                                                                                                                                     
                                                                                                                                        // Класс для тестирования
                                                                                                                                        class TabTest
                                                                                                                                        {
                                                                                                                                        public:
                                                                                                                                            void run();
                                                                                                                                        };
                                                                                                                                     
                                                                                                                                    } // namespace school


                                                                                                                                  cpp-file:
                                                                                                                                  ExpandedWrap disabled
                                                                                                                                    #include "DataTable.h"
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                    #define l(v) std::wcout << #v << " = " << (v) << "\n";
                                                                                                                                     
                                                                                                                                    // Класс-обертка для преобразования в строку
                                                                                                                                    class StringConverter
                                                                                                                                    {
                                                                                                                                    public:
                                                                                                                                        template<typename T>
                                                                                                                                        static std::wstring toString(T val)
                                                                                                                                        {
                                                                                                                                            return (std::wostringstream() << val).str();
                                                                                                                                        }
                                                                                                                                    };
                                                                                                                                     
                                                                                                                                     
                                                                                                                                    // Класс для работы со строками
                                                                                                                                    class MyString : public std::wstring
                                                                                                                                    {
                                                                                                                                    public:
                                                                                                                                        MyString() : std::wstring() {}
                                                                                                                                        MyString(std::wstring    s) : std::wstring(s) {}
                                                                                                                                        MyString(const wchar_t* s) : std::wstring(s) {}
                                                                                                                                     
                                                                                                                                        MyString& operator=(const std::wstring& a)
                                                                                                                                        {
                                                                                                                                            return   *static_cast<std::wstring*>(this) = a, *this;
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        template<typename T>
                                                                                                                                        MyString& operator=(const T a)
                                                                                                                                        {
                                                                                                                                            return *this = StringConverter::toString(a);
                                                                                                                                        }
                                                                                                                                    };
                                                                                                                                     
                                                                                                                                     
                                                                                                                                    // Класс для работы с вектором
                                                                                                                                    template<typename T>
                                                                                                                                    class MyVector : public std::vector<T>
                                                                                                                                    {
                                                                                                                                    public:
                                                                                                                                        T& operator[](const size_t i)
                                                                                                                                        {
                                                                                                                                            if (i >= this->size()) this->resize(i + 1);
                                                                                                                                            return *(this->begin() + i);
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        void resize(size_t new_size, const T& value = T())
                                                                                                                                        {
                                                                                                                                            std::vector<T>::resize(new_size, value);
                                                                                                                                        }
                                                                                                                                    };
                                                                                                                                     
                                                                                                                                     
                                                                                                                                    // Класс для форматирования таблицы
                                                                                                                                    class TableFormatter
                                                                                                                                    {
                                                                                                                                    private:
                                                                                                                                        MyVector<MyVector<MyString>>& m;
                                                                                                                                        MyVector<MyString>& h;
                                                                                                                                        size_t& CMAX;
                                                                                                                                     
                                                                                                                                    public:
                                                                                                                                        TableFormatter(size_t& cmax,
                                                                                                                                            MyVector<MyVector<MyString>>& data,
                                                                                                                                            MyVector<MyString>& header)
                                                                                                                                            : m(data), h(header), CMAX(cmax)
                                                                                                                                        {
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        void format()
                                                                                                                                        {
                                                                                                                                            calculateMaxColumns();
                                                                                                                                            resizeRows();
                                                                                                                                            addRowNumbers();
                                                                                                                                            calculateColumnWidths();
                                                                                                                                            alignColumns();
                                                                                                                                            alignHeaders();
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                    private:
                                                                                                                                        void calculateMaxColumns()
                                                                                                                                        {
                                                                                                                                            for (const auto& e : m)
                                                                                                                                                if (CMAX < e.size())
                                                                                                                                                    CMAX = e.size();
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        void resizeRows()
                                                                                                                                        {
                                                                                                                                            for (auto& e : m)
                                                                                                                                                if (CMAX > e.size()) e.resize(CMAX);
                                                                                                                                     
                                                                                                                                            if (CMAX > h.size()) h.resize(CMAX);
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        void addRowNumbers()
                                                                                                                                        {
                                                                                                                                            for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                            {
                                                                                                                                                m[r][0] = StringConverter::toString(r + 1);
                                                                                                                                            }
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        void calculateColumnWidths()
                                                                                                                                        {
                                                                                                                                            std::vector<size_t> n(CMAX, 0);
                                                                                                                                     
                                                                                                                                            // Инициализация ширинами заголовков
                                                                                                                                            for (size_t i = 0; i < h.size() && i < CMAX; ++i)
                                                                                                                                            {
                                                                                                                                                n[i] = h[i].size();
                                                                                                                                            }
                                                                                                                                     
                                                                                                                                            // Нахождение максимальных ширин
                                                                                                                                            for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                            {
                                                                                                                                                for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                {
                                                                                                                                                    if (n[c] < m[r][c].size())
                                                                                                                                                        n[c] = m[r][c].size();
                                                                                                                                                }
                                                                                                                                            }
                                                                                                                                     
                                                                                                                                            // Выравнивание столбцов
                                                                                                                                            for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                            {
                                                                                                                                                for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                {
                                                                                                                                                    if (n[c] > m[r][c].size())
                                                                                                                                                        m[r][c].resize(n[c], ' ');
                                                                                                                                                }
                                                                                                                                            }
                                                                                                                                     
                                                                                                                                            // Выравнивание заголовков
                                                                                                                                            for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                            {
                                                                                                                                                if (h[c].size() < m[0][c].size())
                                                                                                                                                    h[c].resize(m[0][c].size(), ' ');
                                                                                                                                            }
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        void alignColumns() {} // Заглушка для совместимости с логикой
                                                                                                                                        void alignHeaders() {} // Заглушка для совместимости с логикой
                                                                                                                                    };
                                                                                                                                     
                                                                                                                                     
                                                                                                                                    // Класс для вывода таблицы
                                                                                                                                    class TablePrinter
                                                                                                                                    {
                                                                                                                                    private:
                                                                                                                                        MyVector<MyVector<MyString>>& m;
                                                                                                                                        MyVector<MyString>& h;
                                                                                                                                        size_t& CMAX;
                                                                                                                                     
                                                                                                                                    public:
                                                                                                                                        TablePrinter(
                                                                                                                                            size_t& cmax,
                                                                                                                                            MyVector<MyVector<MyString>>& data,
                                                                                                                                            MyVector<MyString>& header)
                                                                                                                                            : CMAX(cmax), m(data), h(header)
                                                                                                                                        {
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        void print(std::wostream& o)
                                                                                                                                        {
                                                                                                                                            std::wstring line = createLine();
                                                                                                                                     
                                                                                                                                            o << line << '\n';
                                                                                                                                            printHeader(o);
                                                                                                                                            o << '\n' << line << '\n';
                                                                                                                                            printRows(o);
                                                                                                                                            o << line << '\n' << '\n';
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                    private:
                                                                                                                                        std::wstring createLine()
                                                                                                                                        {
                                                                                                                                            std::wstring line;
                                                                                                                                            for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                            {
                                                                                                                                                line += std::wstring(h[c].size() + 3, '=');
                                                                                                                                            }
                                                                                                                                            return line;
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        void printHeader(std::wostream& o)
                                                                                                                                        {
                                                                                                                                            for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                            {
                                                                                                                                                o << ' ' << h[c] << " |";
                                                                                                                                            }
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        void printRows(std::wostream& o)
                                                                                                                                        {
                                                                                                                                            for (const auto& r : m)
                                                                                                                                            {
                                                                                                                                                for (const auto& e : r)
                                                                                                                                                {
                                                                                                                                                    o << ' ' << e << " |";
                                                                                                                                                }   o << '\n';
                                                                                                                                            }
                                                                                                                                        }
                                                                                                                                    };
                                                                                                                                     
                                                                                                                                    // Основной класс таблицы
                                                                                                                                    class Tab
                                                                                                                                    {
                                                                                                                                    private:
                                                                                                                                        MyVector<MyVector<MyString>> m;
                                                                                                                                        MyVector<MyString> h;
                                                                                                                                        size_t CMAX = 0;
                                                                                                                                     
                                                                                                                                    public:
                                                                                                                                        Tab() = default;
                                                                                                                                     
                                                                                                                                        MyVector<MyString>& operator[](const size_t i)
                                                                                                                                        {
                                                                                                                                            if (i >= m.size()) m.resize(i + 1);
                                                                                                                                            return *(m.begin() + i);
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        template<typename ... T>
                                                                                                                                        void head(T ... t)
                                                                                                                                        {
                                                                                                                                            (h.push_back(StringConverter::toString(t)), ...);
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        void formater()
                                                                                                                                        {
                                                                                                                                            TableFormatter formatter(CMAX, m, h);
                                                                                                                                            formatter.format();
                                                                                                                                        }
                                                                                                                                     
                                                                                                                                        friend std::wostream& operator<<(std::wostream&, Tab&);
                                                                                                                                    };
                                                                                                                                     
                                                                                                                                    std::wostream& operator<<(std::wostream& o, Tab& t)
                                                                                                                                    {
                                                                                                                                        t.formater();
                                                                                                                                     
                                                                                                                                        TablePrinter printer(t.CMAX, t.m, t.h);
                                                                                                                                        printer.print(o);
                                                                                                                                     
                                                                                                                                        return o;
                                                                                                                                    }
                                                                                                                                     
                                                                                                                                    ///----------------------------------------------------------------------------|
                                                                                                                                    /// Тест.
                                                                                                                                    ///----------------------------------------------------------------------------:
                                                                                                                                    class TabTest
                                                                                                                                    {
                                                                                                                                    public:
                                                                                                                                        void run()
                                                                                                                                        {   ///-----------------------|
                                                                                                                                            /// Создаём табулятор.    |
                                                                                                                                            ///-----------------------:
                                                                                                                                            Tab tab;
                                                                                                                                     
                                                                                                                                            ///-----------------------|
                                                                                                                                            /// Заголовок.            |
                                                                                                                                            ///-----------------------:
                                                                                                                                            tab.head(L"NN", L"Первый", L"Второй", 3);
                                                                                                                                     
                                                                                                                                            ///-----------------------|
                                                                                                                                            /// Как угодно заполняем. |
                                                                                                                                            ///-----------------------:
                                                                                                                                            tab[1][1] = 2020;
                                                                                                                                            tab[2][2] = "qwerty";
                                                                                                                                            tab[4][3] = 3.14;
                                                                                                                                            tab[0][4] = L"Яша + Оля";
                                                                                                                                     
                                                                                                                                            ///-----------------------|
                                                                                                                                            /// Вывод на экран/файл.  |
                                                                                                                                            ///-----------------------:
                                                                                                                                            std::wcout << tab;
                                                                                                                                     
                                                                                                                                            tab[2][4] = 2025;
                                                                                                                                            tab[3][5] = 'A';
                                                                                                                                     
                                                                                                                                            std::wcout << tab;
                                                                                                                                        }
                                                                                                                                    };


                                                                                                                                  source.cpp:
                                                                                                                                  ExpandedWrap disabled
                                                                                                                                    #include "DataTable.h"
                                                                                                                                     
                                                                                                                                    using namespace school;
                                                                                                                                     
                                                                                                                                    ///----------------------------------------------------------------------------|
                                                                                                                                    /// Старт.
                                                                                                                                    ///----------------------------------------------------------------------------:
                                                                                                                                    int main()
                                                                                                                                    {
                                                                                                                                        setlocale(0, "");
                                                                                                                                     
                                                                                                                                      TabTest test;
                                                                                                                                      test.run();
                                                                                                                                        
                                                                                                                                        return 0;
                                                                                                                                    }
                                                                                                                                    Ну так класс TabTest объявлен в пространстве имён school. Тот, что определён в глобальном, то другой, получается, они не совпадают.
                                                                                                                                      Цитата Qraizer @
                                                                                                                                      Ну так класс TabTest объявлен в пространстве имён school. Тот, что определён в глобальном, то другой, получается, они не совпадают.

                                                                                                                                      То есть, и заголовки и реализаци дожны находиться в одном прострастве имен?
                                                                                                                                        Я разместил код в прострастве имен school, и у меня вылезло куча ошибо. Почемиу?

                                                                                                                                        ExpandedWrap disabled
                                                                                                                                          #include "DataTable.h"
                                                                                                                                           
                                                                                                                                           
                                                                                                                                           
                                                                                                                                          namespace school
                                                                                                                                          {
                                                                                                                                              #define l(v) std::wcout << #v << " = " << (v) << "\n";
                                                                                                                                           
                                                                                                                                              // Класс-обертка для преобразования в строку
                                                                                                                                              class StringConverter
                                                                                                                                              {
                                                                                                                                              public:
                                                                                                                                                  template<typename T>
                                                                                                                                                  static std::wstring toString(T val)
                                                                                                                                                  {
                                                                                                                                                      return (std::wostringstream() << val).str();
                                                                                                                                                  }
                                                                                                                                              };
                                                                                                                                           
                                                                                                                                           
                                                                                                                                              // Класс для работы со строками
                                                                                                                                              class MyString : public std::wstring
                                                                                                                                              {
                                                                                                                                              public:
                                                                                                                                                  MyString() : std::wstring() {}
                                                                                                                                                  MyString(std::wstring    s) : std::wstring(s) {}
                                                                                                                                                  MyString(const wchar_t* s) : std::wstring(s) {}
                                                                                                                                           
                                                                                                                                                  MyString& operator=(const std::wstring& a)
                                                                                                                                                  {
                                                                                                                                                      return   *static_cast<std::wstring*>(this) = a, *this;
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  template<typename T>
                                                                                                                                                  MyString& operator=(const T a)
                                                                                                                                                  {
                                                                                                                                                      return *this = StringConverter::toString(a);
                                                                                                                                                  }
                                                                                                                                              };
                                                                                                                                           
                                                                                                                                           
                                                                                                                                              // Класс для работы с вектором
                                                                                                                                              template<typename T>
                                                                                                                                              class MyVector : public std::vector<T>
                                                                                                                                              {
                                                                                                                                              public:
                                                                                                                                                  T& operator[](const size_t i)
                                                                                                                                                  {
                                                                                                                                                      if (i >= this->size()) this->resize(i + 1);
                                                                                                                                                      return *(this->begin() + i);
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  void resize(size_t new_size, const T& value = T())
                                                                                                                                                  {
                                                                                                                                                      std::vector<T>::resize(new_size, value);
                                                                                                                                                  }
                                                                                                                                              };
                                                                                                                                           
                                                                                                                                           
                                                                                                                                              // Класс для форматирования таблицы
                                                                                                                                              class TableFormatter
                                                                                                                                              {
                                                                                                                                              private:
                                                                                                                                                  MyVector<MyVector<MyString>>& m;
                                                                                                                                                  MyVector<MyString>& h;
                                                                                                                                                  size_t& CMAX;
                                                                                                                                           
                                                                                                                                              public:
                                                                                                                                                  TableFormatter(size_t& cmax,
                                                                                                                                                      MyVector<MyVector<MyString>>& data,
                                                                                                                                                      MyVector<MyString>& header)
                                                                                                                                                      : m(data), h(header), CMAX(cmax)
                                                                                                                                                  {
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  void format()
                                                                                                                                                  {
                                                                                                                                                      calculateMaxColumns();
                                                                                                                                                      resizeRows();
                                                                                                                                                      addRowNumbers();
                                                                                                                                                      calculateColumnWidths();
                                                                                                                                                      alignColumns();
                                                                                                                                                      alignHeaders();
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                              private:
                                                                                                                                                  void calculateMaxColumns()
                                                                                                                                                  {
                                                                                                                                                      for (const auto& e : m)
                                                                                                                                                          if (CMAX < e.size())
                                                                                                                                                              CMAX = e.size();
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  void resizeRows()
                                                                                                                                                  {
                                                                                                                                                      for (auto& e : m)
                                                                                                                                                          if (CMAX > e.size()) e.resize(CMAX);
                                                                                                                                           
                                                                                                                                                      if (CMAX > h.size()) h.resize(CMAX);
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  void addRowNumbers()
                                                                                                                                                  {
                                                                                                                                                      for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                      {
                                                                                                                                                          m[r][0] = StringConverter::toString(r + 1);
                                                                                                                                                      }
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  void calculateColumnWidths()
                                                                                                                                                  {
                                                                                                                                                      std::vector<size_t> n(CMAX, 0);
                                                                                                                                           
                                                                                                                                                      // Инициализация ширинами заголовков
                                                                                                                                                      for (size_t i = 0; i < h.size() && i < CMAX; ++i)
                                                                                                                                                      {
                                                                                                                                                          n[i] = h[i].size();
                                                                                                                                                      }
                                                                                                                                           
                                                                                                                                                      // Нахождение максимальных ширин
                                                                                                                                                      for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                      {
                                                                                                                                                          for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                          {
                                                                                                                                                              if (n[c] < m[r][c].size())
                                                                                                                                                                  n[c] = m[r][c].size();
                                                                                                                                                          }
                                                                                                                                                      }
                                                                                                                                           
                                                                                                                                                      // Выравнивание столбцов
                                                                                                                                                      for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                      {
                                                                                                                                                          for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                          {
                                                                                                                                                              if (n[c] > m[r][c].size())
                                                                                                                                                                  m[r][c].resize(n[c], ' ');
                                                                                                                                                          }
                                                                                                                                                      }
                                                                                                                                           
                                                                                                                                                      // Выравнивание заголовков
                                                                                                                                                      for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                      {
                                                                                                                                                          if (h[c].size() < m[0][c].size())
                                                                                                                                                              h[c].resize(m[0][c].size(), ' ');
                                                                                                                                                      }
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  void alignColumns() {} // Заглушка для совместимости с логикой
                                                                                                                                                  void alignHeaders() {} // Заглушка для совместимости с логикой
                                                                                                                                              };
                                                                                                                                           
                                                                                                                                           
                                                                                                                                              // Класс для вывода таблицы
                                                                                                                                              class TablePrinter
                                                                                                                                              {
                                                                                                                                              private:
                                                                                                                                                  MyVector<MyVector<MyString>>& m;
                                                                                                                                                  MyVector<MyString>& h;
                                                                                                                                                  size_t& CMAX;
                                                                                                                                           
                                                                                                                                              public:
                                                                                                                                                  TablePrinter(
                                                                                                                                                      size_t& cmax,
                                                                                                                                                      MyVector<MyVector<MyString>>& data,
                                                                                                                                                      MyVector<MyString>& header)
                                                                                                                                                      : CMAX(cmax), m(data), h(header)
                                                                                                                                                  {
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  void print(std::wostream& o)
                                                                                                                                                  {
                                                                                                                                                      std::wstring line = createLine();
                                                                                                                                           
                                                                                                                                                      o << line << '\n';
                                                                                                                                                      printHeader(o);
                                                                                                                                                      o << '\n' << line << '\n';
                                                                                                                                                      printRows(o);
                                                                                                                                                      o << line << '\n' << '\n';
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                              private:
                                                                                                                                                  std::wstring createLine()
                                                                                                                                                  {
                                                                                                                                                      std::wstring line;
                                                                                                                                                      for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                      {
                                                                                                                                                          line += std::wstring(h[c].size() + 3, '=');
                                                                                                                                                      }
                                                                                                                                                      return line;
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  void printHeader(std::wostream& o)
                                                                                                                                                  {
                                                                                                                                                      for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                      {
                                                                                                                                                          o << ' ' << h[c] << " |";
                                                                                                                                                      }
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  void printRows(std::wostream& o)
                                                                                                                                                  {
                                                                                                                                                      for (const auto& r : m)
                                                                                                                                                      {
                                                                                                                                                          for (const auto& e : r)
                                                                                                                                                          {
                                                                                                                                                              o << ' ' << e << " |";
                                                                                                                                                          }   o << '\n';
                                                                                                                                                      }
                                                                                                                                                  }
                                                                                                                                              };
                                                                                                                                           
                                                                                                                                              // Основной класс таблицы
                                                                                                                                              class Tab
                                                                                                                                              {
                                                                                                                                              private:
                                                                                                                                                  MyVector<MyVector<MyString>> m;
                                                                                                                                                  MyVector<MyString> h;
                                                                                                                                                  size_t CMAX = 0;
                                                                                                                                           
                                                                                                                                              public:
                                                                                                                                                  Tab() = default;
                                                                                                                                           
                                                                                                                                                  MyVector<MyString>& operator[](const size_t i)
                                                                                                                                                  {
                                                                                                                                                      if (i >= m.size()) m.resize(i + 1);
                                                                                                                                                      return *(m.begin() + i);
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  template<typename ... T>
                                                                                                                                                  void head(T ... t)
                                                                                                                                                  {
                                                                                                                                                      (h.push_back(StringConverter::toString(t)), ...);
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  void formater()
                                                                                                                                                  {
                                                                                                                                                      TableFormatter formatter(CMAX, m, h);
                                                                                                                                                      formatter.format();
                                                                                                                                                  }
                                                                                                                                           
                                                                                                                                                  friend std::wostream& operator<<(std::wostream&, Tab&);
                                                                                                                                              };
                                                                                                                                           
                                                                                                                                              std::wostream& operator<<(std::wostream& o, Tab& t)
                                                                                                                                              {
                                                                                                                                                  t.formater();
                                                                                                                                           
                                                                                                                                                  TablePrinter printer(t.CMAX, t.m, t.h);
                                                                                                                                                  printer.print(o);
                                                                                                                                           
                                                                                                                                                  return o;
                                                                                                                                              }
                                                                                                                                           
                                                                                                                                              ///----------------------------------------------------------------------------|
                                                                                                                                              /// Тест.
                                                                                                                                              ///----------------------------------------------------------------------------:
                                                                                                                                              class TabTest
                                                                                                                                              {
                                                                                                                                              public:
                                                                                                                                                  void run()
                                                                                                                                                  {   ///-----------------------|
                                                                                                                                                      /// Создаём табулятор.    |
                                                                                                                                                      ///-----------------------:
                                                                                                                                                      Tab tab;
                                                                                                                                           
                                                                                                                                                      ///-----------------------|
                                                                                                                                                      /// Заголовок.            |
                                                                                                                                                      ///-----------------------:
                                                                                                                                                      tab.head(L"NN", L"Первый", L"Второй", 3);
                                                                                                                                           
                                                                                                                                                      ///-----------------------|
                                                                                                                                                      /// Как угодно заполняем. |
                                                                                                                                                      ///-----------------------:
                                                                                                                                                      tab[1][1] = 2020;
                                                                                                                                                      tab[2][2] = "qwerty";
                                                                                                                                                      tab[4][3] = 3.14;
                                                                                                                                                      tab[0][4] = L"Яша + Оля";
                                                                                                                                           
                                                                                                                                                      ///-----------------------|
                                                                                                                                                      /// Вывод на экран/файл.  |
                                                                                                                                                      ///-----------------------:
                                                                                                                                                      std::wcout << tab;
                                                                                                                                           
                                                                                                                                                      tab[2][4] = 2025;
                                                                                                                                                      tab[3][5] = 'A';
                                                                                                                                           
                                                                                                                                                      std::wcout << tab;
                                                                                                                                                  }
                                                                                                                                              };
                                                                                                                                          };

                                                                                                                                        Прикреплённая картинка
                                                                                                                                        Прикреплённая картинка
                                                                                                                                          Вам же Qraizer сказал.
                                                                                                                                          Объявление и реализация должны быть в одном namespace.
                                                                                                                                          в cpp файле так же должно быть указано
                                                                                                                                          namespace school {
                                                                                                                                          Тут должна быть вся реализация и объявления классов
                                                                                                                                          }

                                                                                                                                          Зы. Таки все объявления классов StringConverter, MyString, MyVector и т.д. я бы перенес в .h Выглядит очень некрасиво.
                                                                                                                                          Сообщение отредактировано: sharky72 -
                                                                                                                                            Цитата sharky72 @
                                                                                                                                            Вам же Qraizer сказал.
                                                                                                                                            Объявление и реализация должны быть в одном namespace.

                                                                                                                                            А у меня разве не в одном namespace?
                                                                                                                                              Цитата DDim1000 @
                                                                                                                                              Цитата sharky72 @
                                                                                                                                              Вам же Qraizer сказал.
                                                                                                                                              Объявление и реализация должны быть в одном namespace.

                                                                                                                                              А у меня разве не в одном namespace?

                                                                                                                                              Неа. Я не вижу namespace school {) в cpp и внутри все что должно ему принадлежать

                                                                                                                                              .h

                                                                                                                                              ExpandedWrap disabled
                                                                                                                                                namespace mynamespace
                                                                                                                                                {
                                                                                                                                                  class classname
                                                                                                                                                  {
                                                                                                                                                     void method1();
                                                                                                                                                     void method2();
                                                                                                                                                  }
                                                                                                                                                 
                                                                                                                                                  void function();
                                                                                                                                                }

                                                                                                                                              .cpp

                                                                                                                                              ExpandedWrap disabled
                                                                                                                                                namespace mynamespace
                                                                                                                                                {
                                                                                                                                                  void classname::method1(){}
                                                                                                                                                  void classname::method2(){}
                                                                                                                                                 
                                                                                                                                                  void function(){}
                                                                                                                                                }
                                                                                                                                              Сообщение отредактировано: sharky72 -
                                                                                                                                                Цитата sharky72 @

                                                                                                                                                Как так? А это что?":
                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                  namespace school
                                                                                                                                                  {
                                                                                                                                                   // ...
                                                                                                                                                  }

                                                                                                                                                Прикреплённая картинка
                                                                                                                                                Прикреплённая картинка
                                                                                                                                                  Так не нужно же дублировать определения. Отдельно, в .cpp, определять нужно только то, что в .h было только объявлено. (В свою очередь в .h определять нужно типы и inline, остальное должно быть только объявлено, а определено в .cpp)
                                                                                                                                                    Ну я же не вижу где находится ваш класс Tab и судя по ошибке его нет в данном namespace. Не говоря о том что по скрину MyString и MyVector, StringConverter определены как в .h так и в .cpp поэтому ошибка двойного определения С2011
                                                                                                                                                    Не надо выкладывать скрины. Либо выкладывайте проект, либо заворачивайте в /code. С телефона смотреть не всегда удобно, не говоря о том что скрин показывает только часть кода.

                                                                                                                                                    Как должны выглядеть объявление и реализация я вам написал.
                                                                                                                                                    Сообщение отредактировано: sharky72 -
                                                                                                                                                      Например, класс TabTest не содержит inline методов, поэтому определён правильно: метод TabTest::run() только объявлен. Но определение в .cpp должно быть только для метода:
                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                        namespace school
                                                                                                                                                        {
                                                                                                                                                        /* ... */
                                                                                                                                                            ///----------------------------------------------------------------------------|
                                                                                                                                                            /// Тест.
                                                                                                                                                            ///----------------------------------------------------------------------------:
                                                                                                                                                            void TabTest::run()
                                                                                                                                                            {
                                                                                                                                                        /* ... */
                                                                                                                                                            }
                                                                                                                                                        }
                                                                                                                                                      Потому что только он и остался не определённым.

                                                                                                                                                      Добавлено
                                                                                                                                                      P.S. Если ранее писал на Джаве (Шарпы, мэйби?), то в Плюсах так тоже можно, но не приветствуется. Только в отдельных случаях
                                                                                                                                                      Сообщение отредактировано: Qraizer -
                                                                                                                                                        Я так понял, что у меня пробле с загаловками? Потому что в одном файле все работает.

                                                                                                                                                        Source.cpp:
                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                          #include <iostream>
                                                                                                                                                          #include <sstream>
                                                                                                                                                          #include <string>
                                                                                                                                                          #include <vector>
                                                                                                                                                          #include <locale>
                                                                                                                                                           
                                                                                                                                                           
                                                                                                                                                          #define l(v) std::wcout << #v << " = " << (v) << "\n";
                                                                                                                                                           
                                                                                                                                                          // Класс-обертка для преобразования в строку
                                                                                                                                                          class StringConverter
                                                                                                                                                          {
                                                                                                                                                          public:
                                                                                                                                                              template<typename T>
                                                                                                                                                              static std::wstring toString(T val)
                                                                                                                                                              {
                                                                                                                                                                  return (std::wostringstream() << val).str();
                                                                                                                                                              }
                                                                                                                                                          };
                                                                                                                                                           
                                                                                                                                                           
                                                                                                                                                          // Класс для работы со строками
                                                                                                                                                          class MyString : public std::wstring
                                                                                                                                                          {
                                                                                                                                                          public:
                                                                                                                                                              MyString() : std::wstring() {}
                                                                                                                                                              MyString(std::wstring    s) : std::wstring(s) {}
                                                                                                                                                              MyString(const wchar_t* s) : std::wstring(s) {}
                                                                                                                                                           
                                                                                                                                                              MyString& operator=(const std::wstring& a)
                                                                                                                                                              {
                                                                                                                                                                  return   *static_cast<std::wstring*>(this) = a, *this;
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              template<typename T>
                                                                                                                                                              MyString& operator=(const T a)
                                                                                                                                                              {
                                                                                                                                                                  return *this = StringConverter::toString(a);
                                                                                                                                                              }
                                                                                                                                                          };
                                                                                                                                                           
                                                                                                                                                           
                                                                                                                                                          // Класс для работы с вектором
                                                                                                                                                          template<typename T>
                                                                                                                                                          class MyVector : public std::vector<T>
                                                                                                                                                          {
                                                                                                                                                          public:
                                                                                                                                                              T& operator[](const size_t i)
                                                                                                                                                              {
                                                                                                                                                                  if (i >= this->size()) this->resize(i + 1);
                                                                                                                                                                  return *(this->begin() + i);
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              void resize(size_t new_size, const T& value = T())
                                                                                                                                                              {
                                                                                                                                                                  std::vector<T>::resize(new_size, value);
                                                                                                                                                              }
                                                                                                                                                          };
                                                                                                                                                           
                                                                                                                                                           
                                                                                                                                                          // Класс для форматирования таблицы
                                                                                                                                                          class TableFormatter
                                                                                                                                                          {
                                                                                                                                                          private:
                                                                                                                                                              MyVector<MyVector<MyString>>& m;
                                                                                                                                                              MyVector<MyString>& h;
                                                                                                                                                              size_t& CMAX;
                                                                                                                                                           
                                                                                                                                                          public:
                                                                                                                                                              TableFormatter(size_t& cmax,
                                                                                                                                                                  MyVector<MyVector<MyString>>& data,
                                                                                                                                                                  MyVector<MyString>& header)
                                                                                                                                                                  : m(data), h(header), CMAX(cmax)
                                                                                                                                                              {
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              void format()
                                                                                                                                                              {
                                                                                                                                                                  calculateMaxColumns();
                                                                                                                                                                  resizeRows();
                                                                                                                                                                  addRowNumbers();
                                                                                                                                                                  calculateColumnWidths();
                                                                                                                                                                  alignColumns();
                                                                                                                                                                  alignHeaders();
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                          private:
                                                                                                                                                              void calculateMaxColumns()
                                                                                                                                                              {
                                                                                                                                                                  for (const auto& e : m)
                                                                                                                                                                      if (CMAX < e.size())
                                                                                                                                                                          CMAX = e.size();
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              void resizeRows()
                                                                                                                                                              {
                                                                                                                                                                  for (auto& e : m)
                                                                                                                                                                      if (CMAX > e.size()) e.resize(CMAX);
                                                                                                                                                           
                                                                                                                                                                  if (CMAX > h.size()) h.resize(CMAX);
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              void addRowNumbers()
                                                                                                                                                              {
                                                                                                                                                                  for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                                  {
                                                                                                                                                                      m[r][0] = StringConverter::toString(r + 1);
                                                                                                                                                                  }
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              void calculateColumnWidths()
                                                                                                                                                              {
                                                                                                                                                                  std::vector<size_t> n(CMAX, 0);
                                                                                                                                                           
                                                                                                                                                                  // Инициализация ширинами заголовков
                                                                                                                                                                  for (size_t i = 0; i < h.size() && i < CMAX; ++i)
                                                                                                                                                                  {
                                                                                                                                                                      n[i] = h[i].size();
                                                                                                                                                                  }
                                                                                                                                                           
                                                                                                                                                                  // Нахождение максимальных ширин
                                                                                                                                                                  for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                                  {
                                                                                                                                                                      for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                                      {
                                                                                                                                                                          if (n[c] < m[r][c].size())
                                                                                                                                                                              n[c] = m[r][c].size();
                                                                                                                                                                      }
                                                                                                                                                                  }
                                                                                                                                                           
                                                                                                                                                                  // Выравнивание столбцов
                                                                                                                                                                  for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                                  {
                                                                                                                                                                      for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                                      {
                                                                                                                                                                          if (n[c] > m[r][c].size())
                                                                                                                                                                              m[r][c].resize(n[c], ' ');
                                                                                                                                                                      }
                                                                                                                                                                  }
                                                                                                                                                           
                                                                                                                                                                  // Выравнивание заголовков
                                                                                                                                                                  for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                                  {
                                                                                                                                                                      if (h[c].size() < m[0][c].size())
                                                                                                                                                                          h[c].resize(m[0][c].size(), ' ');
                                                                                                                                                                  }
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              void alignColumns() {} // Заглушка для совместимости с логикой
                                                                                                                                                              void alignHeaders() {} // Заглушка для совместимости с логикой
                                                                                                                                                          };
                                                                                                                                                           
                                                                                                                                                           
                                                                                                                                                          // Класс для вывода таблицы
                                                                                                                                                          class TablePrinter
                                                                                                                                                          {
                                                                                                                                                          private:
                                                                                                                                                              MyVector<MyVector<MyString>>& m;
                                                                                                                                                              MyVector<MyString>& h;
                                                                                                                                                              size_t& CMAX;
                                                                                                                                                           
                                                                                                                                                          public:
                                                                                                                                                              TablePrinter(
                                                                                                                                                                  size_t& cmax,
                                                                                                                                                                  MyVector<MyVector<MyString>>& data,
                                                                                                                                                                  MyVector<MyString>& header)
                                                                                                                                                                  : CMAX(cmax), m(data), h(header)
                                                                                                                                                              {
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              void print(std::wostream& o)
                                                                                                                                                              {
                                                                                                                                                                  std::wstring line = createLine();
                                                                                                                                                           
                                                                                                                                                                  o << line << '\n';
                                                                                                                                                                  printHeader(o);
                                                                                                                                                                  o << '\n' << line << '\n';
                                                                                                                                                                  printRows(o);
                                                                                                                                                                  o << line << '\n' << '\n';
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                          private:
                                                                                                                                                              std::wstring createLine()
                                                                                                                                                              {
                                                                                                                                                                  std::wstring line;
                                                                                                                                                                  for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                                  {
                                                                                                                                                                      line += std::wstring(h[c].size() + 3, '=');
                                                                                                                                                                  }
                                                                                                                                                                  return line;
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              void printHeader(std::wostream& o)
                                                                                                                                                              {
                                                                                                                                                                  for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                                  {
                                                                                                                                                                      o << ' ' << h[c] << " |";
                                                                                                                                                                  }
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              void printRows(std::wostream& o)
                                                                                                                                                              {
                                                                                                                                                                  for (const auto& r : m)
                                                                                                                                                                  {
                                                                                                                                                                      for (const auto& e : r)
                                                                                                                                                                      {
                                                                                                                                                                          o << ' ' << e << " |";
                                                                                                                                                                      }   o << '\n';
                                                                                                                                                                  }
                                                                                                                                                              }
                                                                                                                                                          };
                                                                                                                                                           
                                                                                                                                                          // Основной класс таблицы
                                                                                                                                                          class Tab
                                                                                                                                                          {
                                                                                                                                                          private:
                                                                                                                                                              MyVector<MyVector<MyString>> m;
                                                                                                                                                              MyVector<MyString> h;
                                                                                                                                                              size_t CMAX = 0;
                                                                                                                                                           
                                                                                                                                                          public:
                                                                                                                                                              Tab() = default;
                                                                                                                                                           
                                                                                                                                                              MyVector<MyString>& operator[](const size_t i)
                                                                                                                                                              {
                                                                                                                                                                  if (i >= m.size()) m.resize(i + 1);
                                                                                                                                                                  return *(m.begin() + i);
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              template<typename ... T>
                                                                                                                                                              void head(T ... t)
                                                                                                                                                              {
                                                                                                                                                                  (h.push_back(StringConverter::toString(t)), ...);
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              void formater()
                                                                                                                                                              {
                                                                                                                                                                  TableFormatter formatter(CMAX, m, h);
                                                                                                                                                                  formatter.format();
                                                                                                                                                              }
                                                                                                                                                           
                                                                                                                                                              friend std::wostream& operator<<(std::wostream&, Tab&);
                                                                                                                                                          };
                                                                                                                                                           
                                                                                                                                                          std::wostream& operator<<(std::wostream& o, Tab& t)
                                                                                                                                                          {
                                                                                                                                                              t.formater();
                                                                                                                                                           
                                                                                                                                                              TablePrinter printer(t.CMAX, t.m, t.h);
                                                                                                                                                              printer.print(o);
                                                                                                                                                           
                                                                                                                                                              return o;
                                                                                                                                                          }
                                                                                                                                                           
                                                                                                                                                          ///----------------------------------------------------------------------------|
                                                                                                                                                          /// Тест.
                                                                                                                                                          ///----------------------------------------------------------------------------:
                                                                                                                                                          class TabTest
                                                                                                                                                          {
                                                                                                                                                          public:
                                                                                                                                                              void run()
                                                                                                                                                              {   ///-----------------------|
                                                                                                                                                                  /// Создаём табулятор.    |
                                                                                                                                                                  ///-----------------------:
                                                                                                                                                                  Tab tab;
                                                                                                                                                           
                                                                                                                                                                  ///-----------------------|
                                                                                                                                                                  /// Заголовок.            |
                                                                                                                                                                  ///-----------------------:
                                                                                                                                                                  tab.head(L"NN", L"Первый", L"Второй", 3);
                                                                                                                                                           
                                                                                                                                                                  ///-----------------------|
                                                                                                                                                                  /// Как угодно заполняем. |
                                                                                                                                                                  ///-----------------------:
                                                                                                                                                                  tab[1][1] = 2020;
                                                                                                                                                                  tab[2][2] = L"qwerty";
                                                                                                                                                                  tab[4][3] = 3.14;
                                                                                                                                                                  tab[0][4] = L"Яша + Оля";
                                                                                                                                                           
                                                                                                                                                                  ///-----------------------|
                                                                                                                                                                  /// Вывод на экран/файл.  |
                                                                                                                                                                  ///-----------------------:
                                                                                                                                                                  std::wcout << tab;
                                                                                                                                                           
                                                                                                                                                                  tab[2][4] = 2025;
                                                                                                                                                                  tab[3][5] = L'A';
                                                                                                                                                           
                                                                                                                                                                  std::wcout << tab;
                                                                                                                                                              }
                                                                                                                                                          };
                                                                                                                                                           
                                                                                                                                                          ///----------------------------------------------------------------------------|
                                                                                                                                                          /// Старт.
                                                                                                                                                          ///----------------------------------------------------------------------------:
                                                                                                                                                          int main()
                                                                                                                                                          {
                                                                                                                                                            setlocale(0, "ru");
                                                                                                                                                           
                                                                                                                                                            TabTest test;
                                                                                                                                                            test.run();
                                                                                                                                                              
                                                                                                                                                              return 0;
                                                                                                                                                          }
                                                                                                                                                          У вас проблема в том что вы и в заголовок и в cpp файл впихнули одно и то же.
                                                                                                                                                          Вы уж определитесь нужен ли вам в данном случае вообще заголовок. Если больше никто этот ваш код использовть не будет и нигде кроме этого файла эти классы не понадобятся - то да, можно и так.
                                                                                                                                                          Если же вы хотите написать нормально и не копировать код в другом файле - то в заголовок размещается объявление классов, функций, дефайнов (если они влияют на несколько единиц трансляции), а вся реализация - выносится в cpp файл.
                                                                                                                                                          Сообщение отредактировано: sharky72 -
                                                                                                                                                            Цитата sharky72 @
                                                                                                                                                            ...
                                                                                                                                                            Если же вы хотите написать нормально и не копировать код в другом файле - то в заголовок размещается объявление классов, функций, дефайнов (если они влияют на несколько единиц трансляции), а вся реализация - выносится в cpp файл.

                                                                                                                                                            Я так и хочу сделать, заголовки разместить в h-файле, а реализацию в cpp-файл. Но проблема в том, что я не понимаю как в данном случае вынести заголовки.
                                                                                                                                                              Вы понимаете разницу между объявлением и реализацией?
                                                                                                                                                              Я же вам привел пример объявления класса в .h и реализации его методов в .cpp

                                                                                                                                                              Как исправить ошибку: "LNK2019 ссылка на неразрешенный внешний символ"?

                                                                                                                                                              Ну почитайте хотя бы основы C++
                                                                                                                                                              https://www.learncpp.com/cpp-tutorial/class...d-header-files/
                                                                                                                                                              Сообщение отредактировано: sharky72 -
                                                                                                                                                                Я отредактировал код, но одна ошибка осталась: идентификатор "run" не определен.
                                                                                                                                                                Подскажите, пожалуйста, как исправить ошибку?

                                                                                                                                                                Файл дикларации:
                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                  #pragma once
                                                                                                                                                                   
                                                                                                                                                                  #include <iostream>
                                                                                                                                                                  #include <sstream>
                                                                                                                                                                  #include <string>
                                                                                                                                                                  #include <vector>
                                                                                                                                                                  #include <locale>
                                                                                                                                                                   
                                                                                                                                                                  namespace school {
                                                                                                                                                                          #define l(v) std::wcout << #v << " = " << (v) << "\n";
                                                                                                                                                                   
                                                                                                                                                                          // Класс-обертка для преобразования в строку
                                                                                                                                                                          class StringConverter
                                                                                                                                                                          {
                                                                                                                                                                          public:
                                                                                                                                                                              template<typename T>
                                                                                                                                                                              static std::wstring toString(T val)
                                                                                                                                                                              {
                                                                                                                                                                                  return (std::wostringstream() << val).str();
                                                                                                                                                                              }
                                                                                                                                                                          };
                                                                                                                                                                   
                                                                                                                                                                   
                                                                                                                                                                          // Класс для работы со строками
                                                                                                                                                                          class MyString : public std::wstring
                                                                                                                                                                          {
                                                                                                                                                                          public:
                                                                                                                                                                              MyString();
                                                                                                                                                                              MyString(std::wstring    s);
                                                                                                                                                                              MyString(const wchar_t* s);
                                                                                                                                                                   
                                                                                                                                                                              template<typename T>
                                                                                                                                                                              MyString& operator=(const T a)
                                                                                                                                                                              {
                                                                                                                                                                                  return *this = StringConverter::toString(a);
                                                                                                                                                                              };
                                                                                                                                                                          };
                                                                                                                                                                   
                                                                                                                                                                   
                                                                                                                                                                          // Класс для работы с вектором
                                                                                                                                                                          template<typename T>
                                                                                                                                                                          class MyVector : public std::vector<T>
                                                                                                                                                                          {
                                                                                                                                                                          public:
                                                                                                                                                                              T& operator[](const size_t i)
                                                                                                                                                                              {
                                                                                                                                                                                  if (i >= this->size()) this->resize(i + 1);
                                                                                                                                                                                  return *(this->begin() + i);
                                                                                                                                                                              }
                                                                                                                                                                   
                                                                                                                                                                              void resize(size_t new_size, const T& value = T())
                                                                                                                                                                              {
                                                                                                                                                                                  std::vector<T>::resize(new_size, value);
                                                                                                                                                                              }
                                                                                                                                                                          };
                                                                                                                                                                   
                                                                                                                                                                   
                                                                                                                                                                          // Класс для форматирования таблицы
                                                                                                                                                                          class TableFormatter
                                                                                                                                                                          {
                                                                                                                                                                          private:
                                                                                                                                                                              MyVector<MyVector<MyString>>& m;
                                                                                                                                                                              MyVector<MyString>& h;
                                                                                                                                                                              size_t& CMAX;
                                                                                                                                                                   
                                                                                                                                                                          public:
                                                                                                                                                                              TableFormatter(size_t& cmax,
                                                                                                                                                                                  MyVector<MyVector<MyString>>& data,
                                                                                                                                                                                  MyVector<MyString>& header);
                                                                                                                                                                   
                                                                                                                                                                              void format();
                                                                                                                                                                   
                                                                                                                                                                          private:
                                                                                                                                                                              void calculateMaxColumns();
                                                                                                                                                                              void resizeRows();
                                                                                                                                                                              void addRowNumbers();
                                                                                                                                                                              void calculateColumnWidths();
                                                                                                                                                                   
                                                                                                                                                                              void alignColumns(); // Заглушка для совместимости с логикой
                                                                                                                                                                              void alignHeaders(); // Заглушка для совместимости с логикой
                                                                                                                                                                          };
                                                                                                                                                                   
                                                                                                                                                                   
                                                                                                                                                                          // Класс для вывода таблицы
                                                                                                                                                                          class TablePrinter
                                                                                                                                                                          {
                                                                                                                                                                          private:
                                                                                                                                                                              MyVector<MyVector<MyString>>& m;
                                                                                                                                                                              MyVector<MyString>& h;
                                                                                                                                                                              size_t& CMAX;
                                                                                                                                                                   
                                                                                                                                                                          public:
                                                                                                                                                                              TablePrinter(
                                                                                                                                                                                  size_t& cmax,
                                                                                                                                                                                  MyVector<MyVector<MyString>>& data,
                                                                                                                                                                                  MyVector<MyString>& header);
                                                                                                                                                                   
                                                                                                                                                                              void print(std::wostream& o);
                                                                                                                                                                   
                                                                                                                                                                          private:
                                                                                                                                                                              std::wstring createLine();
                                                                                                                                                                   
                                                                                                                                                                              void printHeader(std::wostream& o);
                                                                                                                                                                   
                                                                                                                                                                              void printRows(std::wostream& o);
                                                                                                                                                                          };
                                                                                                                                                                   
                                                                                                                                                                          // Основной класс таблицы
                                                                                                                                                                          class Tab
                                                                                                                                                                          {
                                                                                                                                                                          private:
                                                                                                                                                                              MyVector<MyVector<MyString>> m;
                                                                                                                                                                              MyVector<MyString> h;
                                                                                                                                                                              size_t CMAX = 0;
                                                                                                                                                                   
                                                                                                                                                                          public:
                                                                                                                                                                             // Tab() = default
                                                                                                                                                                              Tab();
                                                                                                                                                                   
                                                                                                                                                                              // объявление оператора[]
                                                                                                                                                                              MyVector<MyString>& operator[](const size_t i);
                                                                                                                                                                   
                                                                                                                                                                              template<typename ... T>
                                                                                                                                                                              void head(T ... t)
                                                                                                                                                                              {
                                                                                                                                                                                  (h.push_back(StringConverter::toString(t)), ...);
                                                                                                                                                                              }
                                                                                                                                                                   
                                                                                                                                                                              void formater();
                                                                                                                                                                   
                                                                                                                                                                              // Объявляем дружественные классы
                                                                                                                                                                              friend class TableFormatter;
                                                                                                                                                                              friend class TablePrinter;
                                                                                                                                                                              friend std::wostream& operator<<(std::wostream& o, Tab& t);
                                                                                                                                                                          };
                                                                                                                                                                   
                                                                                                                                                                          std::wostream& operator<<(std::wostream& o, Tab& t);
                                                                                                                                                                   
                                                                                                                                                                          ///----------------------------------------------------------------------------|
                                                                                                                                                                          /// Тест.
                                                                                                                                                                          ///----------------------------------------------------------------------------:
                                                                                                                                                                          class TabTest
                                                                                                                                                                          {
                                                                                                                                                                          public:
                                                                                                                                                                              void run();
                                                                                                                                                                          };
                                                                                                                                                                  } // namespace school


                                                                                                                                                                Файл реализации:
                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                  #include "DataTable.h"
                                                                                                                                                                   
                                                                                                                                                                   
                                                                                                                                                                  namespace school {
                                                                                                                                                                   
                                                                                                                                                                      // Реализация методов MyString
                                                                                                                                                                      MyString::MyString() : std::wstring() {}
                                                                                                                                                                   
                                                                                                                                                                      MyString::MyString(std::wstring s) : std::wstring(s) {}
                                                                                                                                                                   
                                                                                                                                                                      MyString::MyString(const wchar_t* s) : std::wstring(s) {}
                                                                                                                                                                   
                                                                                                                                                                      // Явная инстанциация шаблонов
                                                                                                                                                                      template class MyVector<MyString>;
                                                                                                                                                                      template class MyVector<MyVector<MyString>>;
                                                                                                                                                                   
                                                                                                                                                                      // Реализация TableFormatter
                                                                                                                                                                      TableFormatter::TableFormatter(size_t& cmax,
                                                                                                                                                                          MyVector<MyVector<MyString>>& data,
                                                                                                                                                                          MyVector<MyString>& header)
                                                                                                                                                                          : m(data), h(header), CMAX(cmax)
                                                                                                                                                                      {
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      void TableFormatter::format()
                                                                                                                                                                      {
                                                                                                                                                                          calculateMaxColumns();
                                                                                                                                                                          resizeRows();
                                                                                                                                                                          addRowNumbers();
                                                                                                                                                                          calculateColumnWidths();
                                                                                                                                                                          alignColumns();
                                                                                                                                                                          alignHeaders();
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      void TableFormatter::calculateMaxColumns()
                                                                                                                                                                      {
                                                                                                                                                                          for (const auto& e : m)
                                                                                                                                                                              if (CMAX < e.size())
                                                                                                                                                                                  CMAX = e.size();
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      void TableFormatter::resizeRows()
                                                                                                                                                                      {
                                                                                                                                                                          for (auto& e : m)
                                                                                                                                                                              if (CMAX > e.size()) e.resize(CMAX);
                                                                                                                                                                   
                                                                                                                                                                          if (CMAX > h.size()) h.resize(CMAX);
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      void TableFormatter::addRowNumbers()
                                                                                                                                                                      {
                                                                                                                                                                          for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                                          {
                                                                                                                                                                              m[r][0] = StringConverter::toString(r + 1);
                                                                                                                                                                          }
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      void TableFormatter::calculateColumnWidths()
                                                                                                                                                                      {
                                                                                                                                                                          std::vector<size_t> n(CMAX, 0);
                                                                                                                                                                   
                                                                                                                                                                          // Инициализация ширинами заголовков
                                                                                                                                                                          for (size_t i = 0; i < h.size() && i < CMAX; ++i)
                                                                                                                                                                          {
                                                                                                                                                                              n[i] = h[i].size();
                                                                                                                                                                          }
                                                                                                                                                                   
                                                                                                                                                                          // Нахождение максимальных ширин
                                                                                                                                                                          for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                                          {
                                                                                                                                                                              for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                                              {
                                                                                                                                                                                  if (n[c] < m[r][c].size())
                                                                                                                                                                                      n[c] = m[r][c].size();
                                                                                                                                                                              }
                                                                                                                                                                          }
                                                                                                                                                                   
                                                                                                                                                                          // Выравнивание столбцов
                                                                                                                                                                          for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                                          {
                                                                                                                                                                              for (size_t r = 0; r < m.size(); ++r)
                                                                                                                                                                              {
                                                                                                                                                                                  if (n[c] > m[r][c].size())
                                                                                                                                                                                      m[r][c].resize(n[c], ' ');
                                                                                                                                                                              }
                                                                                                                                                                          }
                                                                                                                                                                   
                                                                                                                                                                          // Выравнивание заголовков
                                                                                                                                                                          for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                                          {
                                                                                                                                                                              if (h[c].size() < m[0][c].size())
                                                                                                                                                                                  h[c].resize(m[0][c].size(), ' ');
                                                                                                                                                                          }
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      void TableFormatter::alignColumns() {}
                                                                                                                                                                      void TableFormatter::alignHeaders() {}
                                                                                                                                                                   
                                                                                                                                                                      // Реализация TablePrinter
                                                                                                                                                                      TablePrinter::TablePrinter(
                                                                                                                                                                          size_t& cmax,
                                                                                                                                                                          MyVector<MyVector<MyString>>& data,
                                                                                                                                                                          MyVector<MyString>& header)
                                                                                                                                                                          : CMAX(cmax), m(data), h(header)
                                                                                                                                                                      {
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      void TablePrinter::print(std::wostream& o)
                                                                                                                                                                      {
                                                                                                                                                                          std::wstring line = createLine();
                                                                                                                                                                   
                                                                                                                                                                          o << line << '\n';
                                                                                                                                                                          printHeader(o);
                                                                                                                                                                          o << '\n' << line << '\n';
                                                                                                                                                                          printRows(o);
                                                                                                                                                                          o << line << '\n' << '\n';
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      std::wstring TablePrinter::createLine()
                                                                                                                                                                      {
                                                                                                                                                                          std::wstring line;
                                                                                                                                                                          for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                                          {
                                                                                                                                                                              line += std::wstring(h[c].size() + 3, '=');
                                                                                                                                                                          }
                                                                                                                                                                          return line;
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      void TablePrinter::printHeader(std::wostream& o)
                                                                                                                                                                      {
                                                                                                                                                                          for (size_t c = 0; c < CMAX; ++c)
                                                                                                                                                                          {
                                                                                                                                                                              o << ' ' << h[c] << " |";
                                                                                                                                                                          }
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      void TablePrinter::printRows(std::wostream& o)
                                                                                                                                                                      {
                                                                                                                                                                          for (const auto& r : m)
                                                                                                                                                                          {
                                                                                                                                                                              for (const auto& e : r)
                                                                                                                                                                              {
                                                                                                                                                                                  o << ' ' << e << " |";
                                                                                                                                                                              }
                                                                                                                                                                              o << '\n';
                                                                                                                                                                          }
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      // Реализация Tab
                                                                                                                                                                      //Tab::Tab() {};
                                                                                                                                                                      Tab::Tab() = default;
                                                                                                                                                                   
                                                                                                                                                                      MyVector<MyString>& Tab::operator[](const size_t i)
                                                                                                                                                                      {
                                                                                                                                                                          if (i >= m.size()) m.resize(i + 1);
                                                                                                                                                                          return *(m.begin() + i);
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      void Tab::formater()
                                                                                                                                                                      {
                                                                                                                                                                          TableFormatter formatter(CMAX, m, h);
                                                                                                                                                                          formatter.format();
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      // Реализация оператора вывода
                                                                                                                                                                      std::wostream& operator<<(std::wostream& o, Tab& t)
                                                                                                                                                                      {
                                                                                                                                                                          t.formater();
                                                                                                                                                                   
                                                                                                                                                                          TablePrinter printer(t.CMAX, t.m, t.h);
                                                                                                                                                                          printer.print(o);
                                                                                                                                                                   
                                                                                                                                                                          return o;
                                                                                                                                                                      }
                                                                                                                                                                   
                                                                                                                                                                      // Реализация TabTest
                                                                                                                                                                      void TabTest::run()
                                                                                                                                                                      {
                                                                                                                                                                          ///-----------------------|
                                                                                                                                                                          /// Создаём табулятор.    |
                                                                                                                                                                          ///-----------------------:
                                                                                                                                                                          Tab tab;
                                                                                                                                                                   
                                                                                                                                                                          ///-----------------------|
                                                                                                                                                                          /// Заголовок.            |
                                                                                                                                                                          ///-----------------------:
                                                                                                                                                                          tab.head(L"NN", L"Первый", L"Второй", 3);
                                                                                                                                                                   
                                                                                                                                                                          ///-----------------------|
                                                                                                                                                                          /// Как угодно заполняем. |
                                                                                                                                                                          ///-----------------------:
                                                                                                                                                                          tab[1][1] = 2020;
                                                                                                                                                                          tab[2][2] = "qwerty";
                                                                                                                                                                          tab[4][3] = 3.14;
                                                                                                                                                                          tab[0][4] = L"Яша + Оля";
                                                                                                                                                                   
                                                                                                                                                                          ///-----------------------|
                                                                                                                                                                          /// Вывод на экран/файл.  |
                                                                                                                                                                          ///-----------------------:
                                                                                                                                                                          std::wcout << tab;
                                                                                                                                                                   
                                                                                                                                                                          tab[2][4] = 2025;
                                                                                                                                                                          tab[3][5] = 'A';
                                                                                                                                                                   
                                                                                                                                                                          std::wcout << tab;
                                                                                                                                                                      };
                                                                                                                                                                  }


                                                                                                                                                                Файл Source.cpp:
                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                  #include "DataTable.h";
                                                                                                                                                                   
                                                                                                                                                                  using namespace school;
                                                                                                                                                                   
                                                                                                                                                                  int main()
                                                                                                                                                                  {
                                                                                                                                                                    setlocale(0, "ru");
                                                                                                                                                                   
                                                                                                                                                                    TabTest test;
                                                                                                                                                                    test,run();
                                                                                                                                                                      
                                                                                                                                                                      return 0;
                                                                                                                                                                  }


                                                                                                                                                                Добавлено
                                                                                                                                                                Все, нашел ошибку.
                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                   TabTest test;
                                                                                                                                                                    test,run();

                                                                                                                                                                Теперь программа компилируется, запускается, но на консоль ничего не выводится,кроме этого сообщения:
                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                  D:\Programming\VS\source\repos\Test\x64\Debug\Test.exe (процесс 30896) завершил работу с кодом -1073741571 (0xc00000fd).
                                                                                                                                                                  Нажмите любую клавишу, чтобы закрыть это окно:

                                                                                                                                                                Почему?
                                                                                                                                                                Сообщение отредактировано: DDim1000 -
                                                                                                                                                                  Цитата DDim1000 @
                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                    D:\Programming\VS\source\repos\Test\x64\Debug\Test.exe (процесс 30896) завершил работу с кодом -1073741571 (0xc00000fd).
                                                                                                                                                                  0xc00000fd – переполнение стека, похоже.

                                                                                                                                                                  Добавлено
                                                                                                                                                                  P.S. Ты на предупреждения не смотришь?
                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                    DataTable.h(36) : warning C4717: school::MyString::operator=<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > >: рекурсия на всех путях выполнения, функция вызовет переполнение стека
                                                                                                                                                                    Цитата Qraizer @
                                                                                                                                                                    P.S. Ты на предупреждения не смотришь?

                                                                                                                                                                    Никаких предупреждений не вижу. Сборка проходит без ошибок и предупреждений.
                                                                                                                                                                    Прикреплённая картинка
                                                                                                                                                                    Прикреплённая картинка


                                                                                                                                                                    Добавлено
                                                                                                                                                                    Все, увидил.
                                                                                                                                                                    1>D:\Programming\VS\source\repos\Test\Test\DataTable.h(36,1): warning C4717: school::MyString::operator=<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > >: рекурсия на всех путях выполнения, функция вызовет переполнение стека

                                                                                                                                                                    Почему так проиходит?
                                                                                                                                                                      Решение:

                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                        // ...
                                                                                                                                                                         
                                                                                                                                                                                // Класс для работы со строками
                                                                                                                                                                                class MyString : public std::wstring
                                                                                                                                                                                {
                                                                                                                                                                                public:
                                                                                                                                                                                    MyString();
                                                                                                                                                                                    MyString(std::wstring    s);
                                                                                                                                                                                    MyString(const wchar_t* s);
                                                                                                                                                                         
                                                                                                                                                                                    template<typename T>
                                                                                                                                                                                    MyString& operator=(const T a)
                                                                                                                                                                                    {
                                                                                                                                                                                        std::wstring temp = StringConverter::toString(a);
                                                                                                                                                                                        this->assign(temp); // используем базовую реализацию assign из wstring
                                                                                                                                                                                        return *this;
                                                                                                                                                                                    };
                                                                                                                                                                                };
                                                                                                                                                                         
                                                                                                                                                                        // ...
                                                                                                                                                                        Цитата DDim1000 @
                                                                                                                                                                        Почему так проиходит?
                                                                                                                                                                        Потому что template<typename T> MyString& operator=(const T a) принимает любой T, в частности и std::wstring тоже. Поэтому operator=() в строке *this = StringConverter::toString(a) после преобразования любого T в std::wstring снова вызывает сам себя, но уже с T, выведенным как std::wstring, что в свою очередь опять вызовет StringConverter::toString() с аргументом std::wstring в качестве T, т.к. template<typename T> std::wstring StringConverter::toString(T val) опять-таки принимает любой T.
                                                                                                                                                                        Чтобы этого не происходило, нужно отвязать MyString::operator=() от std::wstring, предоставив более специализированную реализацию, или использовать какой-нибудь operator=(), не принадлежащий MyString.

                                                                                                                                                                        Добавлено
                                                                                                                                                                        Я бы написал
                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                          std::wstring temp = StringConverter::toString(a);
                                                                                                                                                                                          this->assign(std::move(temp)); // используем базовую реализацию assign из wstring
                                                                                                                                                                        чтобы сразу переместить. Это не критично, но работать будет быстрее.
                                                                                                                                                                        P.S. Если с семантикой перемещения пока не знаком, не бери в голову. Больше путаться будешь, чем выигрывать от оптимизации.

                                                                                                                                                                        Добавлено
                                                                                                                                                                        P.P.S. Ты реализовал второе решение разрыва рекурсии, с использованием методов, не принадлежащих MyString. Альтернативный вариант с более специализированным operator=() может быть таким: просто добавить ещё один operator=(), который перегрузит шаблонный:
                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                            MyString& operator=(const std::wstring& a)
                                                                                                                                                                            {
                                                                                                                                                                              this->std::wstring::operator=(a);
                                                                                                                                                                          /* как вариант:
                                                                                                                                                                              *static_cast<std::wstring*>(this) = a;
                                                                                                                                                                             сработает, т.к. std::wstring является базовым для MyString, и в нём есть свой operator=(std::wstring)
                                                                                                                                                                          */
                                                                                                                                                                              return *this;
                                                                                                                                                                            }
                                                                                                                                                                        Тут тоже используется альтернативный operator=(), предоставляемый std::wstring, мы его просто используем в подходящий момент. Т.к. MyString& MyString::operator=(const std::wstring&) нешаблонный, он априори более специализирован, чем шаблонный, поэтому при прочих равных компилятор выберет его.

                                                                                                                                                                        Добавлено
                                                                                                                                                                        Позволь совет на будущее: если программа собирается и даже запускается, это ещё не означает, что с ней всё в порядке. Это должно быть и так понятно, конечно, иначе бы программы после успешной сборки всегда работали идеально. Компилятор не может залезть тебе в голову и понять, что ты хотел написать, поэтому компилит ровно то, что ты написал, а не что хотел написать. Но предупреждения компиляторам выдумали не просто так. Он всё-таки пытается понять написанное в рамках своей скудной разумности, и если увидит что-то непротиворечащее правилам Языка, однако с его точки зрения странное, код-то он соберёт, но предупредит, что тут что-то с его точки зрения не так. Предупреждениям компиляторы не зря научили, к ним всегда стоит присматриваться. Многие этого не понимают и просто их игнорируют, мол, собралось же. Однако даже самое незначительное на первый взгляд, типа "локальная переменная определена и не используется" иногда может указывать на серьёзную ошибку: вместо неё в программе заюзана одноимённая глобальная. Всегда стоит стараться избавляться от предупреждений, причём ни в коем случае не подавлением (кроме ситуаций, когда это зависит не от тебя, и ты просто ничего не можешь сделать; типичный пример – ругательства компилятора на несоответствие знаковости типов внутри какого-нибудь <sys/socket.h>, ибо не ты писал этот идиотский API, а Беркли), а путём исправления кода, иначе за простынёй неважных предупреждений запросто пропустишь реально важные.
                                                                                                                                                                        Сообщение отредактировано: Qraizer -
                                                                                                                                                                          Именно поэтому на всех серьезных проектах ставят warning as error и warning level 4.
                                                                                                                                                                            Цитата sharky72 @
                                                                                                                                                                            Именно поэтому на всех серьезных проектах ставят warning as error и warning level 4.

                                                                                                                                                                            Это что такое, warning as error и warning level 4?
                                                                                                                                                                            Сообщение отредактировано: DDim1000 -
                                                                                                                                                                              Уровни предупреждений от 1 и до... обычно 4, но бывает и больше (у Intel compiler, например, 5) определяют степень важности предупреждения, по какой-то там шкале. Чем больше цифра, тем менее важное. У каждого предупреждения есть некий уровень, и он фиксирован для него. Когда выставляешь желаемый уровень диагностики, предупреждения с большим уровнем компилятор подавляет. Например «warning C4018: <: несоответствие типов со знаком и без знака» у Студии имеет уровень 3, а «warning C4389: ==: несоответствие типов со знаком и без знака» уровень 4, поэтому выставив желаемый уровень 3, увидишь в диагностике первые, но не увидишь вторых.
                                                                                                                                                                              У разных компиляторов может быть по-разному. Даже распределение предупреждений по уровням, не говоря уже о списке странностей, которые способен обнаружить. По умолчанию уровень обычно 1, когда ставишь 4, компилер будет рассказывать о твоём коде больше, как правило всё, до чего сможет докопаться. Чтобы побить себя по рукам, можно попросить компилятор расценивать любые предупреждения как ошибки, тогда он при обнаружении хотя бы одного, даже самого с его точки зрения некритичного, даже при отсутствии ошибок, будет отказываться собирать код как при ошибках. Довольно кардинально, на спорю. Студия в качестве соломонова решения умеет рассматривать как ошибки только предупреждения с неким указанным уровнем и строже, те, что помягче, не будут стопорить сборку.
                                                                                                                                                                              Сообщение отредактировано: Qraizer -
                                                                                                                                                                                Цитата Qraizer @
                                                                                                                                                                                Уровни предупреждений от 1 и до... обычно 4, но бывает и больше (у Intel compiler, например, 5) определяют степень важности предупреждения, по какой-то там шкале. Чем больше цифра, тем менее важное. У каждого предупреждения есть некий уровень, и он фиксирован для него. Когда выставляешь желаемый уровень диагностики, предупреждения с большим уровнем компилятор подавляет. Например «warning C4018: <: несоответствие типов со знаком и без знака» у Студии имеет уровень 3, а «warning C4389: ==: несоответствие типов со знаком и без знака» уровень 4, поэтому выставив желаемый уровень 3, увидишь в диагностике первые, но не увидишь вторых.
                                                                                                                                                                                У разных компиляторов может быть по-разному. Даже распределение предупреждений по уровням, не говоря уже о списке странностей, которые способен обнаружить. По умолчанию уровень обычно 1, когда ставишь 4, компилер будет рассказывать о твоём коде больше, как правило всё, до чего сможет докопаться. Чтобы побить себя по рукам, можно попросить компилятор расценивать любые предупреждения как ошибки, тогда он при обнаружении хотя бы одного, даже самого с его точки зрения некритичного, даже при отсутствии ошибок, будет отказываться собирать код как при ошибках. Довольно кардинально, на спорю. Студия в качестве соломонова решения умеет рассматривать как ошибки только предупреждения с неким указанным уровнем и строже, те, что помягче, не будут стопорить сборку.

                                                                                                                                                                                Ой, Qraizer, ну ты же знаешь как я тебя уважаю!
                                                                                                                                                                                Но ты часто бываешь такой "душный" =) Ну чтобы просто сказать, мол "увеличение уровня предупреждений увеличивает детализацию сообщений об ошибках". Это всё. Обнять и плакать :'(
                                                                                                                                                                                  У меня пунктик: не просто выдать факт, а объяснить его, идеально – почему так, а не как-нибудь иначе. Связи концепций лучше усваиваются и дают понимание системы, а не просто её знание.
                                                                                                                                                                                    :wall: :lool:
                                                                                                                                                                                    1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                                                                                                                                                    0 пользователей:


                                                                                                                                                                                    Рейтинг@Mail.ru
                                                                                                                                                                                    [ Script execution time: 0,2262 ]   [ 29 queries used ]   [ Generated: 23.10.25, 20:44 GMT ]