【问题标题】:C++ Overloading functions and function templates - different behaviour?C++ 重载函数和函数模板 - 不同的行为?
【发布时间】:2014-01-31 16:05:46
【问题描述】:

我有以下代码:

void A(const int*)
{
    cout << "const int*" << endl;
}

void A(const int&)
{
    cout << "const int&" << endl;
}

template <typename T>
void B(const T*)
{
    cout << "const T*" << endl;
}

template <typename T>
void B(const T&)
{
    cout << "const T&" << endl;
}

int main()
{
    int* a = nullptr;
    A(a);            //output: const int*

    int* b = nullptr;
    B(b);            //output: const T&

    return 0;
}

A(a) 正在调用函数 A(const int*)
B(b) 正在调用模板函数 B(const T&amp;)

由于重载解析的工作方式,我对模板行为并不感到惊讶。但我无法解释为什么非模板函数返回相反的结果(这更直观)。

是不是因为使用非模板函数不需要推导类型并被认为是完全匹配(允许添加 const-ness?)?

我不是元编程和编译器正在做的事情(如重载解析)方面的专家,这就是我有点困惑的原因。

【问题讨论】:

    标签: c++ function templates overloading overload-resolution


    【解决方案1】:

    在对非模板的调用中,您传递了一个指向 int 的指针。那么它如何调用期望引用 int 的函数呢?两者是完全不同的类型。是的,允许添加 const 。如果你在 constness 上超载了:

    void A(const int*)
    {
        cout << "const int*" << endl;
    }
    
    void A(int*)
    {
        cout << "int*" << endl;
    }
    

    将选择非常量版本作为更好的匹配。

    有了模板,事情就不同了。请记住,指针也是类型。将T 推断为指针类型同样有效。当你调用B(b)时,编译器可以使用这个函数:

    template <typename T>
    void B(const T*)
    {
        cout << "const T*" << endl;
    }
    

    在这种情况下,T 必须推导出为 int,并且const T* 变为 const int*,一个指向 const int 的指针。

    或者编译器可以选择这个函数:

    template <typename T>
    void B(const T&)
    {
        cout << "const T&" << endl;
    }
    

    在这种情况下,T 被推断为int*。而const T&amp;则变成int* const&amp;,也就是一个指向int的const指针的引用。

    因为在第二种情况下,T 精确映射到您实际传入的内容(指向 int 的指针),所以它是更好的匹配。

    【讨论】:

    • 他在问为什么它调用非模板化的A 而不是模板化的A,而不是为什么它不调用B
    • @WilliamCustode:不,他不是。没有模板化的A
    • @WilliamCustode 没有A 函数模板。
    • 我在问为什么模板的行为与非模板版本不同。我在 B(b) 调用中再次传递指向 int 的指针,它调用的是 B(const T&),而不是 B(const T*)
    • @getoff:我可以回答(我会编辑)但你说你对模板的行为并不感到惊讶。所以我假设你理解它。这就是为什么我的回答只解释了非模板行为。
    【解决方案2】:

    不,行为没有什么不同。

    使用 B,T 被解析为 int* 和第二个重载

    int* const&
    

    比第一个重载的匹配更好

    int const*
    

    请注意,两者都是可行的,只是第一个更好。因此,基本上该模板可以让您获得最允许的访问权限。

    对于 A,实际上只有一个选择,因为指针不能转换为引用,那就是删除 const。

    【讨论】:

      猜你喜欢
      • 2012-09-02
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多