Статья: Альтернативные Интерфейсы
PFC old = set_slist_handler(my_handler);
// код, в котором в случае ошибок в slist
// будет использоваться мой обработчик my_handler
set_slist_handler(old); // восстановление
}
Чтобы сделать управление более изящным, slist_hanlder мог бы быть сделан членом класса slist, что позволило бы различным спискам иметь одновременно разные обработчики.
Обобщенные Классы
Очевидно, можно было бы определить списки других типов (classdef*, int, char* и т.д.) точно так же, как был определен класс nlist: простым выводом из класса slist. Процесс определения таких новых типов утомителен (и потому чреват ошибками), но с помощью макросов его можно "механизировать". К сожалению, если пользоваться стандартным C препроцессором, это тоже может оказаться тягостным. Однако полученными в результате макросами пользоваться довольно просто.
Вот пример того, как обобщенный (generic) класс slist, названный gslist, может быть задан как макрос. Сначала для написания такого рода макросов включаются некоторые инструменты из :
.html#include "slist.h"
#ifndef GENERICH
#include
#endif
Обратите внимание на использование #ifndef для того, чтобы гарантировать, что в одной компиляции не будет включен дважды. GENERICH определен в .
После этого с помощью name2(), макроса из для конкатенации имен, определяются имена новых обобщенных классов:
#define gslist(type) name2(type,gslist)
#define gslist_iterator(type) name2(type,gslist_iterator)
И, наконец, можно написать классы gslist(тип) и gslist_iterator(тип):
#define gslistdeclare(type) \
struct gslist(type) : slist { \
int insert(type a) \
{ return slist::insert( ent(a) ); } \
int append(type a) \
{ return slist::append( ent(a) ); } \
type get() { return type( slist::get() ); } \
gslist(type)() { } \
gslist(type)(type a) : (ent(a)) { } \
~gslist(type)() { clear(); } \
}; \
\