LINUX.ORG.RU

C++, шаблон, упростить.


0

2

Класс занимается тем, что представляет мульти-типовое 6-разрядное число, где каждый разряд имеет свой тип. Крутит итераторы: когда младший разряд доходит до end(), он его сбрасывает на begin() и накручивает итератор следующего разряда. Когда доходит до того, что все трераторы равны своим end() - ам, перестаёт идти вперёд.

Проход вперёд реализован в методе increment().

Сея логика не обсуждается, она нужна. Предлагать упрощать архитектуру приложения, которому это понадобилось - не надо, это ведроедный коллайдер шестого порядка на квази-рулезах. Короче, такой функционал нужен.

Хочется упростить реализацию этой многомерной фигни. Есть способы?

template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > class MultiTypeCounter
{
public:
	MultiTypeCounter( const T1& _o1, const T2& _o2, const T3& _o3, const T4& _o4, const T5& _o5, const T6& _o6 )
	: o1( _o1 )
	, o2( _o2 )
	, o3( _o3 )
	, o4( _o4 )
	, o5( _o5 )
	, o6( _o6 )
	{
		it_t1 = o1.begin(); ite_t1 = o1.end();
		it_t2 = o2.begin(); ite_t2 = o2.end();
		it_t3 = o3.begin(); ite_t3 = o3.end();
		it_t4 = o4.begin(); ite_t4 = o4.end();
		it_t5 = o5.begin(); ite_t5 = o5.end();
		it_t6 = o6.begin(); ite_t6 = o6.end();
	}

	// return:
	// true on success
	// false if limit reached
	bool increment()
	{
		do
		{
			if ( it_t1 != ite_t1)
				++it_t1;
			if ( it_t1 != ite_t1 )
				break;
			it_t1 = o1.begin();

			if ( it_t2 != ite_t2)
				++it_t2;
			if ( it_t2 != ite_t2 )
				break;
			it_t2 = o2.begin();

			if ( it_t3 != ite_t3)
				++it_t3;
			if ( it_t3 != ite_t3 )
				break;
			it_t3 = o3.begin();

			if ( it_t4 != ite_t4)
				++it_t4;
			if ( it_t4 != ite_t4 )
				break;
			it_t4 = o4.begin();

			if ( it_t5 != ite_t5)
				++it_t5;
			if ( it_t5 != ite_t5 )
				break;
			it_t5 = o5.begin();

			if ( it_t6 != ite_t6)
				++it_t6;
			if ( it_t6 != ite_t6 )
				break;
			it_t6 = o6.begin();

			// Limit reached
			return false;

		} while ( 0 );
		return true;
	}

	typename T1::const_iterator &iter1() const { return it_t1; }
	typename T2::const_iterator &iter2() const { return it_t2; }
	typename T3::const_iterator &iter3() const { return it_t3; }
	typename T4::const_iterator &iter4() const { return it_t4; }
	typename T5::const_iterator &iter5() const { return it_t5; }
	typename T6::const_iterator &iter6() const { return it_t6; }

private:
	MultiTypeCounter(const MultiTypeCounter&);
	MultiTypeCounter& operator=(const MultiTypeCounter&);

	// const references
	const T1 &o1;
	const T2 &o2;
	const T3 &o3;
	const T4 &o4;
	const T5 &o5;
	const T6 &o6;

	typename T1::const_iterator it_t1, ite_t1;
	typename T2::const_iterator it_t2, ite_t2;
	typename T3::const_iterator it_t3, ite_t3;
	typename T4::const_iterator it_t4, ite_t4;
	typename T5::const_iterator it_t5, ite_t5;
	typename T6::const_iterator it_t6, ite_t6;
};

А в чем сакральный смысел конструкции

do{
...
} while(0);

Что не позволяет натыкать ретурнов вместо бряков?

Можно ли оформить increment как функцию?

template <class T1, class T2, ...> bool increment(T1&, T2& ...){...}

AIv ★★★★★
()
Ответ на: комментарий от Gorthauer

Спасибо К.О. Я с-но хотел спросить у ТС-а, устраивает ли его по дизайну такой вариант (который самый лаконичный) - если мутить через класс букв куда будет больше.

AIv ★★★★★
()
Ответ на: комментарий от Gorthauer

Че то я злой какой то сегодня, невыспавшийся. Там ище должен был смайлик быть ";-)".

AIv ★★★★★
()
Ответ на: комментарий от AIv

Сакральный смысл просто в таком стиле написания кода, разницы нет.

Как функцию - неудобно, ведь надо в неё постоянно передавать эти итераторы, а значит состояние счётчика (суть сумма состояний итераторов) будет храниться за пределами этого моего класса, что идеологически неправильно, ведь счётчик, коим является этот класс, сам должен помнить своё считательное состояние, не возлагая труд памяти на своего пользователя.

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

что идеологически неправильно

Откройте для себя ФП!

ведь счётчик, коим является этот класс, сам должен помнить своё считательное состояние,

Предлагается организовывать счетчик как угодно. Основная фича ж в инкременте, и вот его оформить как ф-ю. С++0x11 юзать можно?

AIv ★★★★★
()
Ответ на: комментарий от AIv

C++0x11 наверное можно, но я сам о нём практически не читал. Можно поподробнее о функциональном варианте реализации (можно за рамками С++ вообще :))

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

Мдя... насчет ФП я загнал, потому что предлагаемый вариант будет менять аргументы. Но все равно это ближе к ФП, перегружать ф-ии в крестах проще чем классы специфицировать, да и иногда удобней разносить код и данные.

В С++0х11 есть такая шняга как Variadic template, самый простой пример с printf-ом http://alenacpp.blogspot.ru/2008/08/variadic-templates.html

AIv ★★★★★
()
Ответ на: комментарий от kiverattes

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

AIv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.