【问题标题】:Rule for which function overload to specialize专门化哪个函数重载的规则
【发布时间】:2020-02-28 07:55:08
【问题描述】:

考虑代码:

#include <iostream>

template <typename T>
void f(T)
{
    std::cout << "Version 1" << std::endl;
}

template <typename T>
void f(T *)
{
    std::cout << "Version 2" << std::endl;
}

template <>
void f<>(int *)
{
    std::cout << "Version 3" << std::endl;
}

int main()
{
    int *p = nullptr;
    f(p);
    return 0;
}

此代码将输出Version 3。发生的情况是函数重载规则查看void f 的前两个版本(第三个版本是专门化的,不参与重载),并决定第二个版本是更好的版本。一旦做出决定,我们就会查看第二个版本是否存在任何专业化。有,我们使用它。

那么,我的问题是:编译器如何知道我的显式特化是第二个重载的特化,而不是第一个重载的特化?我没有为它提供模板参数以供它做出选择。决定要专门化哪个函数是否遵循与决定调用哪个重载类似/相同的规则(如果它正在调用该函数)?这有点道理……

【问题讨论】:

    标签: c++ overloading template-specialization


    【解决方案1】:

    template_argument_deduction#Explicit_instantiation中有那个例子

    模板参数推导用于显式实例化、显式特化和那些声明符 id 恰好引用函数模板的特化的友元声明(例如,friend ostream&amp; operator&lt;&lt; &lt;&gt; (...)),如果不是所有模板参数都显式指定或默认,模板参数推导用于确定引用哪个模板的特化。

    P 是被视为潜在匹配的函数模板的类型,A 是声明中的函数类型。如果没有匹配项或多个匹配项(在部分排序之后),则函数声明格式错误:

    template<class X> void f(X a);  // 1st template f
    template<class X> void f(X* a); // 2nd template f
    template<> void f<>(int* a) { } // explicit specialization of f
    // P1 = void(X), A1 = void(int*): deduced X = int*, f<int*>(int*)
    // P2 = void(X*), A2 = void(int*): deduced X = int, f<int>(int*)
    // f<int*>(int*) and f<int>(int*) are then submitted to partial ordering
    // which selects f<int>(int*) as the more specialized template
    

    【讨论】:

    • 你知道标准中的哪个地方说部分排序完成了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-12
    相关资源
    最近更新 更多