在何处/如何定义模板

时间:2010-02-09 17:26:12

标签: c++ templates header inline definition

在C ++中定义模板的最佳实践是什么?

template <class T>
class A
{
private:
    // stuff
public:
    T DoMagic()
    {
        //method body
    }
}

Or:

template <class T>
class A
{
private:
    // stuff
public:
    T DoMagic();
}

template <class T>
A::T DoMagic()
{
    // magic
}

另一种方式? 我似乎偶然发现了一些关于这个问题的争议。 所以;选择什么途径?

6 个答案:

答案 0 :(得分:4)

这完全是一种风格问题。然而,那说:

  1. 选择一种方式并坚持下去 - 无论是内联还是全部,或根据某些规则混合
  2. 我个人使用3行规则。如果模板中的方法体超过3行,我将其移到外面。
  3. 没有真正的理由不将内联所有定义包含在内(无论如何它们都是编译器POV内联的),然而,许多人认为保持它们分离更加干净,并且允许类定义更具可读性。

答案 1 :(得分:2)

随着您编写的模板变得越来越大,越来越复杂,使用越来越高的分离级别。   无论您如何将定义与声明分开,性能都是相同的,因此您的主要关注点应该是可读性和可维护性。

在编写仅在一个地方使用的简单模板时,请使用CPP文件中的声明内联声明并定义它,您将要在其中使用它。如果只有一个代码块需要此模板,则没有理由强制进行全局重新编译。

file.cpp

template<class Gizmo> bool DoSomethingFancy()
{
 // ...
}

对于翻译单元中使用的小模板实用程序,请在H文件中一起定义和声明它们:

utility.h

template<class Gizmo> bool DoSomethingUseful() 
{
  // ...
}

随着模板变得越来越复杂,能够与定义分开查看声明将变得更加重要。首先,将所有内容分开,但保存在同一个文件中:

utility.h

template<class Type> class Useful
{
  bool FunctionA();
  bool FunctionB();
};

template<class Type> bool Useful<Type>::FunctionA()
{
  // ...
}

template<class Type> bool Useful<Type>::FunctionB()
{
  // ...
}

但最终即使这样也会变得笨拙。如果是,请将其分隔为声明的头文件和定义的INC文件。在头文件的末尾,#include INC文件:

utility.h:

template<class Type> class MoreUseful
    {
      bool FunctionA();
      bool FunctionB();
    };

#include "utility.inc"

utility.inc:

template<class Type> bool MoreUseful<Type>::FunctionA()
{
  // ...
}

template<class Type> bool MoreUseful<Type>::FunctionB()
{
  // ...
}

答案 2 :(得分:1)

这是宗教(风格)问题。我更喜欢在模板声明之外为具有多个方法的类定义我的函数,或者几个方法很简单。

在任何一种情况下,我的理解是模板声明和方法定义必须在同一个翻译单元中。这是因为template更像是模板,编译器将给定类型插入模板并为给定类型生成代码。

无论你决定什么,都要保持一致。

答案 3 :(得分:1)

我通常在外面定义所有方法,但每次我希望C ++有某种“模板块”:

template <class T>
struct A
{
     T foo();
     T bar(T * t);
     T baz(T const & t);
};

template <class T>  // Made-up syntax
{
    T A::foo()
    {
        //...
    }

    T A::bar(T * t)
    {
        //...        
    }

    T A::baz(T const & t)
    {
        //...
    }
}

答案 4 :(得分:1)

如果函数是非平凡的(即多于一行或两行),请考虑单独定义它们。这使得类的接口更易于为类的用户导航,阅读和理解,他们很可能不必查看每个方法的实际实现。

答案 5 :(得分:0)

对于像你的例子这样的一次性实例,它没什么区别。

当有很多模板有很多变化时会发生什么?然后它有助于将类似类型的苹果放在一起,并将类似类型的橙子放在一起。当然,这必须尽可能直观地完成。这很大程度上受到使用代码的程序员文化的影响。