Каким макросом я могу заменить шаблон «шаблон …» на что-то более короткое?
т.е. вместо них:
template <typename NodeDataT, typename ArcDataT>
/*constructor*/ GraphDirected::
GraphDirected()
{
}
template <typename NodeDataT, typename ArcDataT>
/*destructor*/ GraphDirected::
~GraphDirected()
{
clear();
}
template <typename NodeDataT, typename ArcDataT>
void GraphDirected::
clear()
{
nodes.clear();
arcs.clear();
}
Я хочу написать это:
boilerplate(/*constructor*/)
GraphDirected()
{
}
boilerplate(/*destructor*/)
~GraphDirected()
{
clear();
}
boilerplate(void)
clear()
{
nodes.clear();
arcs.clear();
}
И, конечно, в конце мне понадобится защита (? #Undef?), Чтобы другие файлы не испортились.
Если не намного сложнее, как можно справиться с такими уродствами?
template <typename ElemType>
typename BST<ElemType>::nodeT * BST<ElemType>::
recFindNode(nodeT *t, ElemType & key) { ... }
Я бы не советовал вам использовать MACRO только для того, чтобы избежать нескольких токенов. Поскольку определения членов шаблона класса должны находиться в одном и том же файле, вы должны определить их в одном и том же файле, даже если вы делаете это вне класса.
Лучшим решением является определять участники внутри самого класса, поэтому вам не нужно повторять токены каждый раз, когда вы определяете участника.
Помните, что шаблоны генерируют ужасные сообщения об ошибках, а MACRO — ЗЛО. Если вы объедините оба, вы увидите еще более ужасные и безумные сообщения об ошибках, когда что-то пойдет не так.
ну, я не вижу ничего плохого, если вы можете украсить шаблон вашего шаблона:
#define pretty ugly
до тех пор, пока вы чувствуете, что это не вредит.
Для типов вы всегда можете сделать typedef
Если вы действительно не любите печатать, вы можете заменить typename
с class
, используйте стандартизированные имена шаблонов для вашего домена приложения и напишите struct
вместо class
чтобы не печатать public:
и, наконец, сделать класс только заголовком:
template <class N, class A>
struct GraphDirected
{
GraphDirected() {} // default constructor
// rest of the class definition
private:
// helpers and data go here
};
Препроцессор C ++ очень мало знает о коде, над которым он работает.
Таким образом, вам необходимо #define
условия, которые вы хотели использовать.
Тем не менее, что-то вроде:
template <typename NodeDataT, typename ArcDataT>
/*constructor*/ GraphDirected::
GraphDirected()
{
}
template <typename NodeDataT, typename ArcDataT>
/*destructor*/ GraphDirected::
~GraphDirected()
{
clear();
}
template <typename NodeDataT, typename ArcDataT>
void GraphDirected::
clear()
{
nodes.clear();
arcs.clear();
}
Можно легко переписать это в каком-то заголовке:
#define boilerplate(rType) boilerplate_template rType boilerplate_class::
И затем в верхней части определения класса:
#define boilerplate_class GraphDirected
#define boilerplate_template template <typename NodeDataT, typename ArcDataT>
Тогда вы можете использовать:
boilerplate(/*constructor*/)
GraphDirected()
{
}
boilerplate(/*destructor*/)
~GraphDirected()
{
clear();
}
boilerplate(void)
clear()
{
nodes.clear();
arcs.clear();
}
Замечания: Как уже отмечали другие, это плохая идея.
Для такого простого случая, как пример два #define
s в верхней части файла объяснит код любому, кто пытается его сохранить. Однако следует помнить, что это может быстро привести к нечитаемому и не поддерживаемому коду. Лучшее решение — использовать редактор, который может выполнить их за вас и сложить так, чтобы вы их не видели. Таким образом, фактический файл остается в более стандартном формате для следующего редактирования (будь то у вас или у другого).