簡體   English   中英

編譯器如何在下面的代碼中通過ADL找到模板函數X :: max(T const&,T const&)?

[英]How does the compiler find the template function X::max(T const&, T const&) through ADL in the code below?

該標准的引用表示贊賞。

#include <iostream>

namespace X {
    class A {};
}

template <typename T>
inline T const& max(T const& a, T const& b, T const& c)
{
    return max(max(a, b), c);
}

inline X::A const& max(X::A const& a, X::A const& b)
{
    std::cout << "non-template" << '\n';
    return a;
}

int main()
{
    X::A a, b, c;
    max(a, b, c);
}

namespace X {
    template <typename T>
    inline T const& max(T const& a, T const& b)
    {
        std::cout << "template" << '\n';
        return a;
    }
}

實例

Standardese

示例中對max()的調用需要一個依賴名稱,因為它的參數取決於模板參數T 此類依賴名稱的兩階段名稱查找在標准中定義如下:

14.6.4.2候選函數[temp.dep.candidate]

1對於post fi x-expression是從屬名稱的函數調用,使用通常的查找規則(3.4.1,3.4.2)找到候選函數,除了:

- 對於使用非標准名稱查找(3.4.1)的查找部分,僅找到模板定義上下文中的函數聲明。

- 對於使用關聯命名空間(3.4.2)的查找部分,僅找到在模板定義上下文或模板實例化上下文中找到的函數聲明。

非限定查找由。定義

3.4.1不合法的名稱查找[basic.lookup.unqual]

1在3.4.1中列出的所有情況下,在每個相應類別中列出的順序中搜索范圍; 一旦找到名稱的聲明,名稱查找就會結束 如果沒有找到聲明,該程序就是格式錯誤。

和參數依賴查找(ADL)為

3.4.2依賴於參數的名稱查找[basic.lookup.argdep]

1當函數調用(5.2.2)中的postfix-expression是非限定id時 ,可以搜索在通常的非限定查找(3.4.1)中未考慮的其他名稱空間,並在這些名稱空間中查找名稱空間范圍的朋友函數或可以找到不可見的函數模板聲明(11.3)。 對搜索的這些修改取決於參數的類型 (以及模板模板參數,模板參數的命名空間)。

你的代碼失敗的原因

在您的示例中,非限定查找和ADL都沒有在定義點找到任何重載因為編譯器還沒有看到任何雙參數max() ADL也適用於實例化 ,並且在那時,編譯器已經看到了雙參數template max(T, T) ,它是唯一可以被調用的template max(T, T) (不同之處在於模板實例在整個翻譯單元被解析后發生)。

更好的代碼

您應該通過將非模板max(X::A, X::A)重載置於namespace X並將template max(T, T)移出其中來修復代碼。

#include <iostream>

// generic code

template <typename T>
inline T const& max(T const& a, T const& b)
{
    std::cout << "template" << '\n';
    return a;
}

template <typename T>
inline T const& max(T const& a, T const& b, T const& c)
{
    using ::max; // fallback if no user-defined max
    return max(max(a, b), c);
}

// X specific code

namespace X {

class A {};

inline X::A const& max(X::A const& a, X::A const& b)
{
    std::cout << "non-template" << '\n';
    return a;
}

} // namespace X

int main()
{
    X::A a, b, c;
    max(a, b, c);
}

實例 - 兩次打印“非模板”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM