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;
};

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

С т.з. конечного пользователя явная разница между макросами (не крестовыми «а вообще») и шаблонами не прослеживается.

С т.з. конечного пользователя этих понятий вообще не существует.

Да, детали реализации различаются.

Вы так и не сказали, что общего. В шаблонах нет ни замены, ни подстановки, их нельзя вызывать. У них гораздо больше общего с дженериками.

Поверьте, в том же питоне макросов нету но я могу их туда засунуть если возникнет острая необходимость

Отлично(я питон тоже знаю и люблю, если что). Но обратите внимание на то, что в языке с динамической типизацией шаблоны вообще бессмысленны и бесполезны. В то время как макросы вполне могут давать профит ;)

генерация кода так прЫнЦыпиально отличается от инстацирования?

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

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

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

А я лично вообще чистую сишечку предпочитаю. Но кресты знаю...

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

Вы так и не сказали, что общего. В шаблонах нет ни замены, ни подстановки, их нельзя вызывать. У них гораздо больше общего с дженериками.

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

template <int D> class vctr{ ... };
И есть порождающая «функция» Vctr(x,y,z,...) возвращающая вектор нужной размерности. Так вот, до недавних пор эта штука была макросом (крестовым), но после перехода на гцц4.7 оно собираться перестало. По просьбам коллег (очень они любят последние компиляторы) пришлось припахать С++0х11 и сделать Vctr через вариадик темплейт.

В то время как макросы вполне могут давать профит ;)

exec в помощь;-)

Тем, что генерация кода - основная задача макроса, в то время как инстанцирование, строго говоря, внутренняя деталь реализации

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

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

в общем этот срачь к топику отношения не имеет, на вопросы от не отвечает )

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

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

Но вызывать их (шаблоны) можно. Вот Вам пример - у меня юзаются декартовы вектора произвольной размерности

...

И есть порождающая «функция» Vctr(x,y,z,...) возвращающая вектор нужной размерности. Так вот, до недавних пор эта штука была макросом (крестовым), но после перехода на гцц4.7 оно собираться перестало. По просьбам коллег (очень они любят последние компиляторы) пришлось припахать С++0х11 и сделать Vctr через вариадик темплейт.

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

Строго говоря, мне пофигу кто из них (компилятор или препроцессор) найдет нужную мне конструкцию.

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

Кстати, я хотел бы поэкспериментировать какое-то время с языком, где есть и дженерики и шаблоны и макросы. Это помогло бы до конца прояснить, что для чего лучше. Но такого языка я не знаю(разве что C++/CLI, но там макросы только обычные сишноплюсовые, а хотелось бы что-нибудь над AST).

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

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

Для макроса есть идентификатор, и под «вызовом» понимается подстановка на место это идентификатора фрагмента кода, возможно с заменой аргументов. Для шаблона тоже есть идентификатор, и под «вызовом» понимается инстацирование, с явной или неявной подстановкой типов. ИМНО очень похоже идеологически, но канешно не тождественно, 100500 отличий.

Пришли к консенсусу, я считаю;-)

Кстати, я хотел бы поэкспериментировать какое-то время с языком, где есть и дженерики и шаблоны и макросы

Питон?;-) ТОлько вот чем там макрос будет отличаться от функции? Разве что у функции свой контекст выполнения,а макрос будет выполняться в контексте где он вызван. Вообще питон очень удобен для таких извращений. Exec-у передается свой объект эмулирующий пр-во имен. Оформляется все через декоратор, который при помощи inspect.getsource выдирает исходник функции и потом ее екзекает. Можно получать доступ к верхним кадрам стека.

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

Пришли к консенсусу, я считаю;-)

Вроде бы да. Но сформулировать итоговый тезис я бы не взялся=)

Питон?;-) ТОлько вот чем там макрос будет отличаться от функции? Разве что у функции свой контекст выполнения,а макрос будет выполняться в контексте где он вызван. Вообще питон очень удобен для таких извращений. Exec-у передается свой объект эмулирующий пр-во имен. Оформляется все через декоратор, который при помощи inspect.getsource выдирает исходник функции и потом ее екзекает. Можно получать доступ к верхним кадрам стека.

Мне кажется придется взять назад свои слова о том, что я знаю питон. Вроде бы все ясно, но ничего похожего я никогда на нем не делал. Даже в голову не приходило.

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

ничего похожего я никогда на нем не делал

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

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