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

343
11 февраля 2017, 07:55

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

#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
 template <class elemType>
    elemType& min (const std::vector<elemType> &vec) {
    typename std::vector<elemType>::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<int> 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|

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

Answer 1

В функции параметр определен как константная ссылка

elemType& min (const std::vector<elemType> &vec) {
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Поэтому такие функции, как begin и end возвращают итератор типа const_iterator. Исправьте

typename std::vector<elemType>::const_iterator
select = vec.begin(), it = next(select), end_it = vec.end();

Также вам следует включить заголовок

#include <iterator>

так как в программе используется функция std::next, объявленная в этом заголовке.

Также имейте в виду, что функция min некорректна, так как в общем случае переданный вектор может быть пустым. А это значит, что в функции имеет место обращение к не существующему элементу вектора и, соответственно, разыменование недействительного итератора.

Имеется стандартный алгоритм std::min_element, объявленный в заголовке <algorithm>, который выполняет поставленную задачу.

Ваша функция может быть определена по аналогии с этим алгоритмом. Например,

#include <iostream>
#include <vector>
template <class elemType>
auto min( const std::vector<elemType> &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<int> 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 <class elemType>
typename std::vector<elemType>::const_iterator min( const std::vector<elemType> &vec ) 
{
    typedef typename std::vector<elemType>::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;
}
Answer 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 не существует (хотя стоит заметить, что есть обратное преобразование), поэтому компилятор и выдал соответствующую ошибку.

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

READ ALSO
Класс с переменными [требует правки]

Класс с переменными [требует правки]

Если глобальных переменных достаточно много, имеет ли смысл объединять их в отдельный класс?

261
Релиз программы

Релиз программы

Пишу программу для windows(xp,7,8,10)

243
Нестандартный синтаксис

Нестандартный синтаксис

Выдаёт ошибку, указывая на boost::thread "нестандартный синтаксис; используйте "&", чтобы создать указатель на член"Что нужно исправить? Если указать...

669