C2440. Ошибка при итерации по элементам массива строк

Рейтинг: 0Ответов: 3Опубликовано: 23.05.2023


Пытаюсь писать клиент-серверный чат. Использую библиотеку boost. В данном случае модуль boost::asio. Код программы я взял из книги по сетевому программированию (https://github.com/Vasilui/habrahabr/blob/master/Boost.Asio_C%2B%2B_Network_Programming/Chapter_4/async_client.cpp)

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

Я проверил, что в функцию старт во время цикла for передаются объекты типа "char *". Возможно(я предполагаю) это и продуцирует ошибку, т.к. функция start требует, чтобы ей передавали объект типа "ссылка на string".

Как мне следует переписать программу, чтобы она отработала без ошибок? Я предполагаю, что можно сделать массив сразу из string - но я не знаю, как потом с ним работать в данных условиях.

Текст ошибки:

Ошибка C2440 инициализация: невозможно преобразовать "const char [5]" в "char *"

Фрагмент кода, описывающий функции start:

static ptr start(ip::tcp::endpoint ep, const std::string& username) {
    ptr new_(new talk_to_svr(username));
    new_->start(ep);
    return new_;
}

Фрагмент кода, в котором возникает ошибка:

int main(int argc, char* argv[]) {
   // TODO: connect several clients
   ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1"), 8001);

   char* names[] = { "John", "James", "Lucy", "Tracy", "Frank", "Abby", 0 };
   for (char** name = names; *name; ++name) {
       talk_to_svr::start(ep, *name);
       boost::this_thread::sleep(boost::posix_time::millisec(100));
   }
    
   service.run();
}

Ответы

▲ -1Принят

Решение оказалось достаточно простым. Рассмотрим функцию start, которая принимает одним из параметров строку. Следовательно необходимо и давать ей строку.

Само решение:

  1. Создаем вектор строк(не забываем в начале подключить вектор: #include <vector> )
  2. Перебираем наш вектор строк

КОД:

int main(int argc, char* argv[]) {
   ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1"), 8001);

   std::vector<std::string> names{"John", "James", "Lucy", "Tracy", "Frank", "Abby" };

   for (const std::string& name : names) {
       talk_to_svr::start(ep, name);
       boost::this_thread::sleep(boost::posix_time::millisec(100));
   }

   service.run();
}

Единственное, что я не понял: зачем в примере, который я указал в самом вопрос использовался 0 в конце массива строк. Я его убрал в своем решении.

▲ 0

Вы не можете менять литералы, это неизменные (константные) строки.

const char* names[] = { "John", "James", "Lucy", "Tracy", "Frank", "Abby", 0 };

Вообще, не стесняйтесь использовать const :)

▲ 0
int main(int argc, char** argv) {
   ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1"), 8001);

   // Размер массива итак известен, т.к. его тип const char*[7]
   // Если вы хотите хранить окончание массива таким образом - используйте nullptr
   const char* names[] = {
       "John", "James", "Lucy", "Tracy", "Frank", "Abby", nullptr
   };

   // Строковые литералы имеют тип const char*,
   // если у них нет префиксов типа L, u8, u, U
   // Неявное преобразование const T -> T запрещено
   for (const char* name = names; *name; ++name) {
       talk_to_svr::start(ep,*name);
       boost::this_thread::sleep(boost::posix_time::millisec(100));

       // Или так 
       using namespace std::literals;
       std::this_thread::sleep_for(100ms);
   }
    
   service.run();
}

Что касается циклов, размер массива подсчитывается компилятором и известен на момент выполнения, так что есть способы проще и выразительнее (nullptr в names при этом не нужен):

template<typename T, std::size_t Size>
constexpr std::size_t count_of(T (&array)[Size]) {
    return Size;
    // return sizeof(array) / sizeof(decltype(*array));
}

// #1 constexpr-функция, которая вернёт размер
for (int idx = 0; idx < count_of(names); ++idx) {
    // names[idx] ...
}

// #2 range-based for loop (with array)
for (auto name : names) {
    // name ...
}

// #3 range-based for loop (with std::initializer_list)
for (auto name : {"John","James","Lucy","Tracy","Frank","Abby"}) {
    // name ...
}