C2440. Ошибка при итерации по элементам массива строк
Пытаюсь писать клиент-серверный чат. Использую библиотеку 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();
}
Ответы (3 шт):
Вы не можете менять литералы, это неизменные (константные) строки.
const char* names[] = { "John", "James", "Lucy", "Tracy", "Frank", "Abby", 0 };
Вообще, не стесняйтесь использовать const :)
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 ...
}
Решение оказалось достаточно простым. Рассмотрим функцию start, которая принимает одним из параметров строку. Следовательно необходимо и давать ей строку.
Само решение:
- Создаем вектор строк(не забываем в начале подключить вектор: #include <vector> )
- Перебираем наш вектор строк
КОД:
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 в конце массива строк. Я его убрал в своем решении.