【问题标题】:How to replace "template <typename ..." with a macro?如何用宏替换“模板<typename ...”?
【发布时间】:2013-01-08 17:46:06
【问题描述】:

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

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

【问题讨论】:

  • 起初我担心有人想要三个标记template &lt;typename的宏。
  • 为什么不在类定义中定义这些方法?
  • @ipc:正是我的想法!
  • 模板函数总是内联。
  • @ipc:不完全是,类型被替换然后编译,这和内联不一样,(顺便说一句:递归函数不能内联,因为你不知道编译时的递归深度时间)

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


【解决方案1】:

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

更好的解决方案是定义成员在类本身内,这样您就不必每次定义成员时都重复标记。

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

【讨论】:

    【解决方案2】:

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

    #define pretty ugly
    

    只要你觉得没有害处。

    对于类型,你总是可以做一个 typedef

    【讨论】:

      【解决方案3】:

      如果你真的不喜欢打字,你可以用class替换typename,为你的应用程序域使用标准化的模板名称,写struct而不是class以避免打字public:,和最后只做类头:

      template <class N, class A>
      struct GraphDirected
      {
          GraphDirected() {} // default constructor
          // rest of the class definition
      
      private:
          // helpers and data go here
      };
      

      【讨论】:

        【解决方案4】:

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

        注意:正如其他人所指出的,这是一个坏主意。 对于像示例这样简单的情况,文件顶部的两个#defines 将向任何试图维护它的人解释代码。但是,请注意,这可能会迅速导致代码不可读和不可维护。一个更好的解决方案是使用一个编辑器,它既可以为你完成这些,也可以将它们折叠起来,这样你就看不到它们了。这样,实际文件在下次编辑(无论是您还是其他人)时仍保持更标准的格式。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-03-18
          • 1970-01-01
          • 1970-01-01
          • 2017-06-22
          • 2016-03-26
          • 1970-01-01
          • 1970-01-01
          • 2015-05-12
          相关资源
          最近更新 更多