Страницы

Поиск по вопросам

среда, 5 февраля 2020 г.

Не пойму что от меня хочет компилятор

#cpp #алгоритм #вектор


Здравствуйте вот есть код, вроде написан правильно, пишу на CodeBlocks:

#include 
#include 
#include 

using namespace std;

 template 
    elemType& min (const std::vector &vec) {
    typename std::vector::iterator
    select = vec.begin(), it = next(select), end_it = vec.end();
    for ( ; it != end_it; it++ ) {
        if ( *it < *select ) select = it;
    }
    return *select;
    };

int main()
{
    int massiv[10] = {35, 66, 98, 15, 32, 41, 24, 90, 55, 100};
    std::vector vec_train(massiv,massiv+10);

    min(vec_train);
    return 0;
}


Но выдает следующую ошибку:


  error: conversion from 'std::vector::const_iterator {aka __gnu_cxx::__normal_iterator
>}' to non-scalar type 'std::vector::iterator {aka __gnu_cxx::__normal_iterator >}'
requested|


Как такие ошибки вообще расшифровывать самостоятельно, если я только недавно начал
учить программирование? Спасибо.
    


Ответы

Ответ 1



В функции параметр определен как константная ссылка elemType& min (const std::vector &vec) { ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Поэтому такие функции, как begin и end возвращают итератор типа const_iterator. Исправьте typename std::vector::const_iterator select = vec.begin(), it = next(select), end_it = vec.end(); Также вам следует включить заголовок #include так как в программе используется функция std::next, объявленная в этом заголовке. Также имейте в виду, что функция min некорректна, так как в общем случае переданный вектор может быть пустым. А это значит, что в функции имеет место обращение к не существующему элементу вектора и, соответственно, разыменование недействительного итератора. Имеется стандартный алгоритм std::min_element, объявленный в заголовке , который выполняет поставленную задачу. Ваша функция может быть определена по аналогии с этим алгоритмом. Например, #include #include template auto min( const std::vector &vec ) { auto select = vec.begin(); if ( select != vec.end() ) { for ( auto it = vec.begin(), end_it = vec.end(); ++it != end_it; ) { if ( *it < *select ) select = it; } } return select; } int main() { int massiv[] = { 35, 66, 98, 15, 32, 41, 24, 90, 55, 100 }; const size_t N = sizeof( massiv ) / sizeof( *massiv ); std::vector vec_train( massiv, massiv + N ); auto it = min( vec_train ); if ( it != vec_train.end() ) { std::cout << "Minimum is " << *it << std::endl; } return 0; } Вывод прогоаммы на консоль Minimum is 15 Если ваш компилятор не поддерживает спецификатор типа auto, то функцию можно определить как template typename std::vector::const_iterator min( const std::vector &vec ) { typedef typename std::vector::const_iterator const_iterator; const_iterator select = vec.begin(); if ( select != vec.end() ) { for ( const_iterator it = vec.begin(), end_it = vec.end(); ++it != end_it; ) { if ( *it < *select ) select = it; } } return select; }

Ответ 2



error: conversion from 'std::vector::const_iterator {aka __gnu_cxx::__normal_iterator >}' to non-scalar type 'std::vector::iterator {aka __gnu_cxx::__normal_iterator >}' requested Как такие ошибки вообще расшифровывать самостоятельно, если я только недавно начал учить программирование? Для начала, из текста ошибки надо выкинуть всё лишнее. В данном случае убрать текст в фигурных скобках вместе со скобками. Он ссылается на внутренний для компилятора тип итератора. "aka" означает "also known as", т.е. по сути, синоним, альтернативное имя. Получим: error: conversion from 'std::vector::const_iterator' to non-scalar type 'std::vector::iterator' requested Здесь уже более чётко видно о чём говорит ошибка: запрошено преобразование из 'std::vector::const_iterator' в нескалярный тип 'std::vector::iterator' Скалярный тип это в частности любой арифметический тип, например, double или int. Между такими типами в c++ предусмотрены неявные преобразования. Т.е. можно написать, скажем: double d = 5.5; int i = d; и компилятор не выдаст на это никаких ошибок. В Вашем случае, тип нескалярный, а значит для неявного преобразования из одного типа T1 в другой T2 должен быть определён: либо конструктор для типа T2, принимающий аргумент типа T1; либо оператор преобразования в типе Т1 вида operator T2(). Преобразования std::vector::const_iterator в std::vector::iterator не существует (хотя стоит заметить, что есть обратное преобразование), поэтому компилятор и выдал соответствующую ошибку. Ну, а про устранение причины ошибки уже подробно расписано в другом ответе, поэтому не вижу смысла повторяться.

Комментариев нет:

Отправить комментарий