重载函数的模板参数推导

问题描述 投票:0回答:1

我有以下代码,我试图理解为什么在第一次调用 fun() 时,编译器选择模板而不是非模板重载 void fun(const int*)。

#include <iostream>
struct test
{
    void fun(const int*)
    {
        std::cout<<"const int * overload\n";
    }
    template<typename T>
    void fun(const T&)
    {
        std::cout<<"template"<<'\n';
    }
};

int main(){
    test t{};
    int * int_ptr;
    t.fun(int_ptr);
    const int * const_int_ptr;
    t.fun(const_int_ptr);
}
c++
1个回答
0
投票

在您的代码中,您有两个

fun
函数的重载:

  1. void fun(const int*)
  2. template<typename T> void fun(const T&)

当您调用

t.fun(int_ptr);
时,编译器需要决定使用哪个重载。这是关键点:仅当没有非模板函数提供更好的匹配时才考虑模板函数

在本例中,

int_ptr
的类型为
int*
。非模板重载
void fun(const int*)
需要一个
const int*
,从编译器的角度来看,与 int*
 相比,
是不同的类型。编译器需要执行从
int*
const int*
的转换,这是允许的,但不是最佳匹配。

另一方面,模板函数

template<typename T> void fun(const T&)
可以实例化为
T
int*
,使参数类型为
const int*&
。这是一个更好的匹配,因为它不需要任何转换。

因此,编译器为第一次调用选择模板重载,因为它更匹配

int*

对于第二次调用,

t.fun(const_int_ptr);
const_int_ptr
的类型为
const int*
,与非模板重载
void fun(const int*)
完全匹配。因此,选择非模板重载。

为了进一步说明不同类型之间的差异,请考虑使用

float
double
的示例:

struct test
{
    void fun(double)
    {
        std::cout << "double overload\n";
    }
    template<typename T>
    void fun(T)
    {
        std::cout << "template\n";
    }
};

int main(){
    test t{};
    float f = 1.0f;
    double d = 1.0;
    t.fun(f); // Calls the template because float and double are different types
    t.fun(d); // Calls the non-template overload because it matches exactly
}

在此示例中:

  • t.fun(f);
    调用模板,因为
    float
    double
    是不同的类型,而模板更适合
    float
  • t.fun(d);
    调用非模板重载,因为
    double
    完全匹配。

以下是代码中调用的摘要:

  • t.fun(int_ptr);
    template<typename T> void fun(const T&)
    搭配更佳。
  • t.fun(const_int_ptr);
    void fun(const int*)
    完全匹配。

我希望这能澄清编译器做出这些选择的原因!如果您还有任何疑问,请随时提问。

© www.soinside.com 2019 - 2024. All rights reserved.