@youkerni
Unity3D developer

C1202 recursive type or function dependency context too complex. В чем причина?

Имеется следующий код для нахождения определителя матрицы.
Не до конца понимаю что значит эта ошибка и где именно получаю переполнение, ведь выход из рекурсии корректный...

spoiler
template<typename _Type, size_t _Size>
_Type MatrixNxN<_Type, _Size>::GetDeterminant()
{
	if (_Size == 2)
		return operator[](0) * operator[](3) - operator[](2) * operator[](1);

	_Type result = 0;

	for (size_t i = 0; i < _Size; i++)
	{
		result += operator[](i) * (i & 0 ? 1 : -1) * GetMinor(i, 0).GetDeterminant();
	}
	return result;
}

template<typename _Type, size_t _Size>
MatrixNxN<_Type, _Size - 1> MatrixNxN<_Type, _Size>::GetMinor(size_t row, size_t col)
{
	size_t index = 0;
	MatrixNxN<_Type, _Size - 1> result;
	for (size_t i = 0; i < _Size; i++)
	{
		if (i == col)
			continue;
		for (size_t j = 0; j < _Size; j++)
		{
			if (j == row)
				continue;
			result[index++] = GetElement(j, i);
		}
	}
	return result;
}
  • Вопрос задан
  • 114 просмотров
Решения вопроса 2
@youkerni Автор вопроса
Unity3D developer
Всем кому интересно - можете глянуть на ответ.
Ответ написан
@MarkusD Куратор тега C++
все время мелю чепуху :)
Судя по коду GetDeterminant() имеет разное поведение для размерности 2 и для остальных размерностей.
Я не буду вдаваться в детали приведенного кода (если честно, там гора ошибок), просто перефразирую его так, чтобы C1202 больше не появлялась.

// Deduction branch. Common determinant calculation.
template< typename TStorage, size_t DIMENSION >
struct DeterminantCalculator final
{
	// Or implement the private instantiation for `DeterminantCalculator<TStorage, 1>`.
	static_assert( DIMENSION > 2, "Dimension of matrix should be >= 2." );
	
	static inline const TStorage Calculate( const MatrixNxN<TStorage, DIMENSION>& matrix )
	{
		TStorage result = 0;
		for( size_t index = 0; index < DIMENSION; ++index )
		{
			// ((index & 0)? 1 : -1) --> always -1.
			// matrix.GetMinor( 0, 0 ) --> uninitialized result.
			// matrix.GetMinor( DIMENSION - 1, 0 ) --> garbage result due to design of `GetMinor`.
			result += matrix[ index ] * ((index & 0)? 1 : -1) * matrix.GetMinor( index, 0 ).GetDeterminant();
		}
		
		return result;
	}
};

// Terminal branch. Determinant for 2x2 matrix.
template< typename TStorage >
struct DeterminantCalculator<TStorage, 2> final
{
	static inline const TStorage Calculate( const MatrixNxN<TStorage, 2>& matrix )
	{
		return matrix[ 0 ] * matrix[ 3 ] - matrix[ 2 ] * matrix[ 1 ];
	}
};

template<typename _Type, size_t _Size>
_Type MatrixNxN<_Type, _Size>::GetDeterminant()
{
	return DeterminantCalculator<_Type, _Size>::Calculate( *this );
}

template<typename _Type, size_t _Size>
MatrixNxN<_Type, _Size - 1> MatrixNxN<_Type, _Size>::GetMinor(size_t row, size_t col)
{
	size_t index = 0;
	MatrixNxN<_Type, _Size - 1> result;
	
	// Should be `i < _Size - 1`, since the `result` is `MatrixNxN<_Type, _Size - 1>`.
	for (size_t i = 0; i < _Size; i++)
	{
		if (i == col)
		{
			// Uninitialized `result` in case of `col == 0`. E.g. ALWAYS.
			continue;
		}
		
		// Should be `i < _Size - 1`, since the `result` is `MatrixNxN<_Type, _Size - 1>`.
		for (size_t j = 0; j < _Size; j++)
		{
			if (j == row)
			{
				// Uninitialized `result` in case of `row == 0`.
				continue;
			}

			result[index++] = GetElement(j, i);
		}
	}
	return result;
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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