【问题标题】:Where/how to define a template在哪里/如何定义模板
【发布时间】:2010-02-09 17:26:12
【问题描述】:

在 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
}

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

【问题讨论】:

  • 我想这在很大程度上取决于方法的长度和复杂程度以及您希望类定义的干净程度。

标签: c++ templates header inline definition


【解决方案1】:

这完全是风格问题。话虽如此:

  1. 选择一种方式并坚持下去——要么全部内联,要么全部出,或者根据某些规则混合
  2. 我个人使用 3 行规则。如果模板中的方法体超过 3 行,我将其移到外面。

没有真正的理由不内联包含所有定义(无论如何它们都是从编译器 POV 内联的),但是,许多人认为将它们分开会更干净,并允许类定义更具可读性。

【讨论】:

  • 好的,所以正如我所料,性能没有差异?由于我习惯于 C# 类定义并且您不能使用头文件,我想我不妨保持定义内联。
  • @Oxymoron:无论如何,模板代码都必须是内联的(也就是说,编译器可以选择是否内联),因为您无法在单独的编译单元中实现它们。
  • @Oxymoron:您可以编译和比较二进制文件——您的示例之间应该没有区别。
【解决方案2】:

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

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

文件.cpp

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

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

实用程序.h

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

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

实用程序.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 文件。头文件末尾#includeINC文件:

实用程序.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()
{
  // ...
}

【讨论】:

    【解决方案3】:

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

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

    无论你决定什么,只要保持一致即可。

    【讨论】:

      【解决方案4】:

      我通常在外面定义所有方法,但每次我希望 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)
          {
              //...
          }
      }
      

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          对于像您的示例这样的一次性实例,它几乎没有什么区别。

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

          【讨论】:

            猜你喜欢
            • 2015-11-27
            • 1970-01-01
            • 2014-12-30
            • 2016-09-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多