【问题标题】:Difference between instantiation and specialization in c++ templatesc++模板中实例化和特化的区别
【发布时间】:2010-10-12 12:26:22
【问题描述】:

在 C++ 模板的上下文中,特化和实例化有什么区别。从我目前所阅读的内容来看,以下是我对专业化和实例化的理解。

template <typename T>
struct Struct
{

     T x;
};

template<>
struct Struct <int> //specialization
{

    //code
};

int main()
{
   Struct <int> s; //specialized version comes into play
   Struct <float> r; // Struct <float> is instantiated by the compiler as shown below

}

编译器对Struct &lt;float&gt; 的实例化

template <typename T=float>
struct Struct
{
    float x;
}

我对模板实例化和特化的理解正确吗?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    (隐式)实例化

    这就是您所说的实例化(如问题中所述)

    显式实例化

    这是当你告诉编译器用给定类型实例化模板时,像这样:

    template Struct<char>; // used to control the PLACE where the template is inst-ed
    

    (显式)专业化

    这就是您所说的专业化(如问题中所述)

    部分专业化

    这是当您为类型子集的模板提供替代定义时,如下所示:

    template<class T> class Struct<T*> {...} // partial specialization for pointers
    

    【讨论】:

    • 在 C++ 标准中(但没有其他地方)也有隐式特化,这是编译器在您实例化模板且未选择显式特化时所做的事情。
    • @Redl Citations about what you say 强烈推荐,如果你有的话。
    • 您的回答很有帮助;我还想提一下stackoverflow.com/a/2351155/1043529——关于共享库有一些注意事项,因为据我所知,一个“未使用”的实例被剥离,而另一个引用实例的实例相信它会在链接期间的某个时刻得到解决.结果是一个相当误导的“未定义引用”,除非您在标题中进行实例化。我认为这个错误意味着我必须提供每一个明确的专业化!
    【解决方案2】:

    在 C++ 模板的上下文中,特化和实例化有什么区别?

    通常(不存在特化)编译器会在使用模板时创建模板的实例化,方法是将实际模板参数(在您的示例中为int)替换为形式模板参数(T),然后编译生成的代码。

    如果存在专业化,那么对于由该专业化指定的(一组)特殊模板参数,将使用该专业化的实现而不是编译器会创建什么。

    【讨论】:

      【解决方案3】:

      模板特化实际上改变了特定类型的模板行为。例如转换为字符串:

      template<typename T> std::string convertToString( const T& t )
      {
         std::ostringstream oss;
         oss << t;
         return oss.str();
      }
      

      让我们专门研究一下,尽管当我们的类型已经是 std::string 时,因为通过 ostringstream 是没有意义的

      template<> std::string convertToString( const std::string & t )
      {
         return t;
      }
      

      你也可以专攻课程。

      现在实例化:这样做是为了允许您将某些类型的编译移动到一个编译单元中。这可以节省编译时间,有时也可以节省代码膨胀。 假设我们将上述内容变成了一个名为 StringConvert 的类,而不是一个函数。

      template<typename T>
      class StringConvert
      {
       public:
        // 4 static functions to convert from T to string, string to T,
         // T to wstring and wstring to T using streams
       };
      

      我们会将大量整数转换为字符串,以便实例化它:将其放在一个标题中

       extern template class StringConvert<int>;
      

      把它放在一个编译单元中:

       template class StringConvert<int>;
      

      请注意,上述操作也可以使用实际上未内联实现的函数来完成(在标题中没有 extern)。您的一个编译单元将实现它们。但是,您的模板仅限于实例化类型。有时在模板具有虚拟析构函数时完成。

      【讨论】:

      • 请注意,我的专业化示例并不是一个很好的示例,因为它是一个函数,因此您可以重载它。但是,如果您需要在类模板中执行此操作,则可以这样做,例如您有一些类型的特征类,其中一个正在转换为字符串。出于演示目的,更容易说明您为什么通过该函数专门针对某个类型。
      【解决方案4】:

      概览

      • 专业化:将模板参数替换为类模板或函数模板的模板参数时获得的类、函数或类成员。

      • 实例化:从模板或类模板成员创建特化的行为。可以从部分特化、类模板成员或主类或函数模板中创建特化。

      显式特化是显式地定义类、函数或成员的特化,没有实例化。

      【讨论】:

      • 是[类模板]成员还是类[模板成员]?
      • 另外 - 也许 - 在给出的完整答案下方,您可以附加两个带有示例的项目符号。
      • @DanNissenbaum 一个“类[模板成员]”也是一个“部分专业化......或主要类或函数模板”,因此被那些覆盖。我的意思是它是一个“[类模板]成员”。这些不是模板,因此我的措辞是“模板或类模板成员”。
      • 第一个项目符号中提到的应该是“类成员”,而不是“类模板成员”(这是标准在定义“专业化”时使用的)。
      【解决方案5】:

      在 c++ 11 中。

      实例化:

      用给定的模板参数实例化模板

      template <typename T>
      struct test{ T m; };
      
      template test<int>;//explicit instantiation
      

      这会导致定义一个标识符为test&lt;int&gt;的结构体

      test<int> a;//implicit instantiation
      

      如果template &lt;typename T&gt; struct test 之前已经用参数T = int 实例化(显式或隐式),那么它只是一个结构实例化。否则,它会先隐式实例化template &lt;typename T&gt; struct test 参数T = int,然后实例化结构test&lt;int&gt; 的实例

      专业化:

      特化是仍然是模板,您仍然需要实例化才能获得真正的代码。

      template <typename T>
      struct test{ T m; };
      template <> struct test<int>{ int newM; } //specialization
      

      模板专业化最有用的可能是您可以为不同的模板参数创建不同的模板,这意味着您可以为不同的模板参数定义不同的类或函数

      template<> struct test<char>{ int cm; }//specialization for char
      test<char> a;
      a.cm = 1;
      
      template<> struct test<long> { int lm; }//specialization for long
      test<long> a;
      a.lm = 1;
      

      除了上面的这些完整模板特化之外,还有(仅类模板)退出部分模板特化

      template<typename T>
      struct test {};
      template <typename T> struct test<const T>{};//partial specialization for const T
      
      
      template <typename A, typename B>
      struct test {};
      template <typename B> struct test<int, B>{};//partial specialization for A = int
      

      【讨论】:

      • 这里是错误的:template test&lt;int&gt;;你必须添加关键字struct
      【解决方案6】:

      专用模板不再只是一个模板。相反,它要么是一个实际的类,要么是一个实际的函数。

      特化来自实例化或显式特化,参见下面的 14.7.4。

      实例化基于主模板定义。一个示例隐式类模板实例化,

      template<typename T>
      class foo {}
      
      foo<int> foo_int_object;
      

      显式类模板实例化示例,

      template class foo<double>;
      

      显式特化的定义与其主模板不同。

      template<>
      class foo<bool> {}
      

      //从标准中提取

      14 个模板

      14.7 模板实例化和特化

      4 实例化模板特化可以为给定参数隐式实例化 (14.7.1) 列出或显式实例化 (14.7.2)。特化是一个类、函数或类成员,它是 实例化或显式特化 (14.7.3)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-10
        相关资源
        最近更新 更多