Здравствуйте вот есть код, вроде написан правильно, пишу на 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|
Как такие ошибки вообще расшифровывать самостоятельно, если я только недавно начал учить программирование? Спасибо.
В функции параметр определен как константная ссылка
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;
}
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
не существует (хотя стоит заметить, что есть обратное преобразование), поэтому компилятор и выдал соответствующую ошибку.
Ну, а про устранение причины ошибки уже подробно расписано в другом ответе, поэтому не вижу смысла повторяться.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Расскажите, пожалуйста, коротко про нее
Если глобальных переменных достаточно много, имеет ли смысл объединять их в отдельный класс?
Выдаёт ошибку, указывая на boost::thread "нестандартный синтаксис; используйте "&", чтобы создать указатель на член"Что нужно исправить? Если указать...