Задать вопрос
@Mishele123

Как исправить проблему с шаблонами?

Есть такой код:
#include <iostream>
#include <vector>
#include <ctime>
#include <stdexcept>


template <typename T>

class Image
{
	int _width;
	int _height;
	std::vector<std::vector<T>> _data;
public:
	Image(int width, int height, bool random) : _width(width), _height(height)
	{
		_data.resize(height, std::vector<T>(width, T(0)));
		if (random)
		{
			std::srand(std::time(nullptr));
			for (int i = 0; i < _height; i++)
			{
				for (int j = 0; j < _width; j++)
				{
					_data[i][j] = static_cast<T>(rand());
				}
			}
		}
	}

	T& operator()(int i, int j) const
	{
		if (i < 0 || i >= _width || j < 0 || j >= _height)
			throw std::out_of_range("Index out of range");
		return _data[j][i];
	}

	// Операторы умножения и сложения на константу
	Image<T> operator*(const T cnst) const
	{
		Image<T> result(_width, _height, false);

		for (int i = 0; i < _height; i++)
		{
			for (int j = 0; j < _width; j++)
			{
				T res = _data[i][j] * cnst;
				if (res < _data[i][j])
					result(i, j) = std::numeric_limits<T>::max();
				else
					result(i, j) = res;
			}
		}
		return result;
	}

	Image<T> operator+(const T cnst) const
	{
		Image<T> result(_width, _height, false);

		for (int i = 0; i < _height; i++)
		{
			for (int j = 0; j < _width; j++)
			{
				T res = _data[i][j] + cnst;
				if (res < _data[i][j])
					result(i, j) = std::numeric_limits<T>::max();
				else
					result(i, j) = res;
			}
		}
		return result;
	}
	
	// Операторы сложения и умножения для bool
	Image<bool> operator+(const Image<bool>& other) const
	{
		if (_width != other._width && _height != other._height)
		{
			throw std::invalid_argument("Размеры изображений не совпадают");
		}
		Image<bool> result(_width, _height, false);

		for (int i = 0; i < _height; i++)
		{
			for (int j = 0; j < _width; j++)
			{
				result(i, j) = _data[i][j] || other._data[i][j];
			}
		}
		return result;
	}

	Image<bool> operator*(const Image<bool>& other) const
	{
		if (_width != other._width && _height != other._height)
		{
			throw std::invalid_argument("Размеры изображений не совпадают");
		}
		Image<bool> result(_width, _height, false);

		for (int i = 0; i < _height; i++)
		{
			for (int j = 0; j < _width; j++)
			{
				result(i, j) = _data[i][j] && other._data[i][j];
			}
		}
		return result;
	}

	// Операторы сложения и умножения разных типов данных
	template <typename Q>
	Image<T> operator+(const Image<Q>& other) const
	{
		if (_width != other._width && _height != other._height)
		{
			throw std::invalid_argument("Размеры изображений не совпадают");
		}
		Image<T> result(_width, _height, false);
		for (int i = 0; i < _height; i++)
		{
			for (int j = 0; j < _width; j++)
			{
				T res = _data[i][j] + static_cast<T>(other._data[i][j]);
				if (res < _data[i][j])
					result(i, j) = std::numeric_limits<T>::max();
				else
					result(i, j) = res;
			}
		}
	}

	template <typename Q>
	Image<T> operator*(const Image<Q>& other) const
	{
		if (_width != other._width && _height != other._height)
		{
			throw std::invalid_argument("Размеры изображений не совпадают");
		}
		Image<T> result(_width, _height, false);
		for (int i = 0; i < _height; i++)
		{
			for (int j = 0; j < _width; j++)
			{
				T res = _data[i][j] * static_cast<T>(other._data[i][j]);
				if (res < _data[i][j])
					result(i, j) = std::numeric_limits<T>::max();
				else
					result(i, j) = res;
			}
		}
	}

	Image<bool> operator!()
	{
		Image<bool> result(_width, _height, false);

		for (int i = 0; i < _height; i++)
		{
			for (int j = 0; j < _width; j++)
			{
				if (_data[i][j] == true)
					result(i, j) = false;
				else
					result(i, j) = true;
			}
		}

		return result;
	}

	Image<T> operator!()
	{
		Image<T> result(_width, _height, false);
		for (int i = 0; i < _height; i++)
		{
			for (int j = 0; j < _width; j++)
			{
				if (_data[i][j] == std::numeric_limits<T>::max())
					result(i, j) = std::numeric_limits<T>::min();
				else
					result(i, j) = -_data[i][j];
			}
		}
		return result;
	}


	float fillFactor() const
	{
		T maxValue = std::numeric_limits<T>::max();
		float sum = 0.0;
		for (int i = 0; i < _height; i++)
		{
			for (int j = 0; j < _width; j++)
			{
				sum += static_cast<T>(_data[i][j]);
			}
		}
		return sum / (_width * _height * maxValue);
	}

};


Ошибки вылезают в месте оператора перегрузки () и Image operator!() возникает ошибка. Если убрать Image operator!(), то только одна ошибка ("невозможно преобразовать const_Ty в T&"). Есть мнение, как это исправить?
  • Вопрос задан
  • 98 просмотров
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 2
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Ошибки вылезают в месте оператора перегрузки () и Image operator!() возникает ошибка.

Это правильно. Нельзя перегрузить функцию (или оператор) только типом возвращаемого значения.

Если убрать Image operator!(), то только одна ошибка ("невозможно преобразовать const_Ty в T&")

Приведённый код эту ошибку не воспроизводит. Но вообще ничто не мешает добавить const в определение оператора !(), поскольку ему не требуется менять исходный объект:
Image<T> operator!() const

Но я вижу другую ошибку: оператор вызова функции определён как константный: T& operator()(int i, int j) const, но возвращает потенциально неконстантную ссылку на внутренности объёкта -- T&. Следующий код поэтому не будет работать: result(i, j) = -_data[i][j];. Нужно либо выбросить ссылку из возвращаемого значения оператора T& operator()(int i, int j) const и переписать реализацию оператора !(), либо добавить неконстантную реализацию оператора вызова функции.
Ответ написан
Комментировать
@vanyamba-electronics
Я кое-что подправил в формулах, поскольку numeric_limits::max() не очень ожидаемый результат выдаёт.
Изменил resize(), чтобы при ресайзе изображения сохранялись исходные данные.
Вектор одноразмерный - потому что по идее будет работать быстрее, чем куча векторов.
Формулу расчёта fill factor я заменил на среднее значение. Потому что не нагуглил ничего похожего.
Мне не очень нравится, что в части функций вектора возвращаются не по указателю, но достигать единообразия я не стал.
Операции с битмапами я сделал по принципу Merge - берутся большие значения длины и высоты.
https://onlinegdb.com/0ULxLQERAp
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы