如何替换“模板

时间:2013-01-08 17:46:06

标签: c++ templates macros c-preprocessor boilerplate

用什么宏可以用更短的东西替换“模板......”样板? 即:而不是这些:

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) { ... }

4 个答案:

答案 0 :(得分:3)

我建议您不要使用MACRO来避免使用少量令牌。由于类模板成员的定义必须在同一个文件中,因此您必须在同一文件中定义它们,即使您在类之外执行此操作。

更好的解决方案是定义中的成员,因此每次定义成员时都不必重复令牌。

请记住,模板会生成丑陋的错误消息,并且MACRO是EVIL。如果你将两者结合起来,当出现问题时,你会看到更加丑陋和疯狂的错误信息。

答案 1 :(得分:0)

好吧,如果你能通过以下方式美化你的模板样板,我认为没有错:

#define pretty ugly

只要你觉得它没有伤害。

对于类型,您始终可以执行typedef

答案 2 :(得分:0)

如果您真的不喜欢打字,可以将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
};

答案 3 :(得分:0)

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将向任何试图维护它的人解释代码。但是,请注意,这可能会导致代码难以读取且无法维护。一个更好的解决方案是使用一个编辑器,既可以为您完成这些并将它们折叠起来,这样您就无法看到它们。这样,实际文件将在下次编辑时保持更标准的格式(无论是您还是其他人)。