【问题标题】:Explicit Specialization in C++C ++中的显式专业化
【发布时间】:2011-06-20 04:33:45
【问题描述】:

我正在阅读 Primer C++ > 函数历险记 > 模板 > 显式特化。

为了说明显式专业化的原因/用途,我们举例说明了一个案例。 考虑一个可以交换任何类型(int、double、struct 等)的交换模板函数(我认为 代码很明显,这里就不写了)

但是有一个特定的结构(称为作业),您只想交换其中的两个成员,而让其余成员保持原样。您将需要不同的定义,因此您必须进行显式专业化。

同一部分中有此声明:- “专业化覆盖常规模板,非模板函数覆盖 两个都。” 为什么不为该用途创建一个(常规)函数?那么常规/非模板会覆盖模板吗?

如果我的解决方案是正确的,那么什么是显式专业化的好例子?

【问题讨论】:

    标签: c++ templates template-specialization


    【解决方案1】:

    显式特化的一个用例是避免在实际template 函数发生某些更改时跳过常规函数。要理解,请参见下面的示例:

    template<typename T1, typename T2>
    void foo(T1 o1, T2 o2)  // template function
    {}
    void foo(int o1, int o2) // regular function overloaded
    {}
    

    到现在还好。现在过了一段时间你必须改变template&lt;&gt; foo()的定义

    template<typename T1, typename T2, typename T3> // new parameter added
    void foo(T1 o1, T2 o2, T3 o3)  // template function
    {}
    

    您相应地更改了对foo() 的所有调用,但是您错过/弄乱了来更改常规重载函数foo()。那么,这是一场灾难!因为编译会顺利进行,并且常规调用会静默template&lt;&gt; foo() 替换,这是不受欢迎的。

    现在,是否有明确的专业化,例如,

    template<>
    void foo(int o1, int o2) // explicit specialization
    {}
    

    那么那个函数会因为参数不匹配而给你编译错误,这会提醒你相应的变化。

    另一种用法或(区别)是显式专用函数可以包含在头文件中,而无需担心多符号链接错误。 请注意,显式专业化也有其自身的缺点,但我演示了它的一个好的方面。

    【讨论】:

    • template&lt;&gt; void foo(int o1, int o2) {...} 不是专门化template&lt;typename T1, typename T2&gt; void foo(T1 o1, T2 o2) {...} 的正确语法。正确的语法是template&lt;&gt; void foo&lt;int,int&gt;(int o1, int o2) {...}
    • @Serge,第一个语法同样正确,它也可以用 gcc 编译。您建议的第二种语法也是正确的,但是当您已经将参数作为参数提及时,提及函数的 &lt;int,int&gt; 是多余的。不过,该语法对于 class 专业化很有用。
    • @iammilind:我并不是说代码不正确或无法编译。我是说这不是template&lt;typename T1, typename T2&gt; void foo(T1 o1, T2 o2) {...} 专业化的正确语法。事实上template&lt;&gt; void foo(int o1, int o2) {...} 是不同的函数模板重载(模板参数为零)。
    • @Serge Dundich,如果是这种情况,那么值得提出一个新问题来了解 2 版本之间的差异。也许我们会得到更多的投入。一样的。因为如果两个版本不同,那么两者都可能相互过载。这不会发生ideone.com/TQYU9
    • @iammilind:“如果两个版本不同,那么两者都可以互相重载。这不会发生”它们确实可能都是重载的候选者,并且最专业的函数模板重载获胜(像往常一样) .
    【解决方案2】:

    为什么不做一个(常规)函数 为了那个用途?然后一个 常规/非模板将覆盖 模板?

    当然,如果适合您,您可以使用常规函数重载而不是显式函数模板特化。但是如果显式使用函数模板(通过指定模板参数),则不会使用常规函数重载。

    示例:

    你有函数模板:

    template< class T >
    void foo( T& x, const T& y )
    {
    ...
    }
    

    那么如果你指定函数重载:

    void foo( double& x, const double& y )
    {
    ....
    }
    

    在这样的代码中:

    template< class T >
    void some_function( T& x )
    {
        T y;
        ......
        foo<T>( x, y );
    }
    

    永远不会使用函数重载void foo( double&amp; x, const double&amp; y )

    但是如果你指定函数模板特化

    template<>
    void foo<double>( double& x, const double& y )
    {
    ....
    }
    

    如果你打电话,some_function 会使用你的专长

    double x;
    
    some_function(x);
    

    某处。

    【讨论】:

      【解决方案3】:

      标准函数可以是特化的,但不能重载,仅举一个例子。另一个例子是类型是不可推导的,并且您有现有的代码使用显式模板参数调用它们 - 那么您的重载毫无价值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-28
        • 2013-12-05
        • 2020-07-18
        • 2021-07-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多