psilogic: (Default)
psilogic ([personal profile] psilogic) wrote2009-07-19 06:21 pm

Зодачка

Специально для любителей шОблоноф и прочих C++ наворотов. :) Сразу пердупердяю: задачка с подвохом.

Дано.

В программе есть некоторое количество классов, которые являются элементами односвязных списков с internal storage (проще говоря, это когда указатель на следующий элемент является членом класса).

Классы имеют вид:
class MyClass...
{
   MyClass *nextListItem;


Причем, варьируется не только название класса, но и название поля "nextListItem".

Задача.

Написать универсальную функцию вставки в начало списка с применением template, inline и pointer-to-member операторов. На входе должны быть: вставляемый элемент; указатель на первый элемент; название поля, указывающего на следующий элемент и тип класса. Функция может быть глобальной или членом namespace или функцией какого-либо нового класса - важно, чтобы она была одна, но работала для всех тех классов. Функция должна работать примерно так же, как ниже представленный #define:

#define INSERT_TO_LIST(firstItemPtr, item, nextItemName) \
(item)->nextItemName= (firstItemPtr), (firstItemPtr)= (item)


Посчитать количество строк в полученной функции. Факультативно: перечислить и обосновать преимущества перед приведенным #define.

[identity profile] dii.livejournal.com 2009-07-19 06:49 pm (UTC)(link)
namespace ops
{

	template <class T>
	struct node_traits
	{
		typedef void undefined_next_member_ptr ;
		static undefined_next_member_ptr next_ptr() ;
	};

#define DECLARE_NEXT_PTR(className, nextNodeName) \
	template <> struct ::ops::node_traits<className> \
	{ \
		static className * className::*next_ptr() \
		{ \
			static className * className::* const t = &className::nextNodeName ; \
			return t ; \
		} \
	} ;


	template <class T>
	void prepend(T * &first_item, T * new_item)
	{
		T * T::* const next_item_name = node_traits<T>::next_ptr() ;
		new_item->*next_item_name= first_item ;
		first_item = new_item ;
	}

} // ops


struct node
{
	node(node * next = 0, int val = 0): next_(next), val_(val) {}
	node * next_ ;
	int val_ ;
} ;
DECLARE_NEXT_PTR(node, next_)


int main(array<System::String ^> ^args)
{
	node n1(0, 111) ;
	node n2(0, 222) ;

	node * p1 = &n1 ;
	node * p2 = &n2 ;

	ops::prepend(p2, p1) ;

	return 0;
}



Писанины, конечно, побольше :)
Но есть и преимущества:
- не нужно каждый раз писать название указателя на следующий член;
- значительное повышение вашей незаменимости для работодателя :)

[identity profile] psilogic.livejournal.com 2009-07-19 06:54 pm (UTC)(link)
это откуда ужасть такая? :)))))

[identity profile] dii.livejournal.com 2009-07-19 06:55 pm (UTC)(link)
из головы только что придумал

[identity profile] psilogic.livejournal.com 2009-07-19 07:03 pm (UTC)(link)
вы там поосторожнее с мухоморами :)))

[identity profile] http://technorati.com/people/technorati/ketmar (from livejournal.com) 2009-07-20 06:39 am (UTC)(link)
O_O

с похмелюги почитал — гойлова ещё сильней заболела…