簡體   English   中英

第一個朋友 function 模板聲明通過“使用命名空間”可見,但通過限定名稱查找不可見

[英]first friend function template declaration is visible through `using namespace` but not through qualified name lookup

我有以下代碼,我用 C++11 編譯。這段代碼是對現實世界用法的簡化。

namespace bar {
template<int M = 10>
struct S {
    template<int N = M*2>
    friend int foo(S) { 
        return N-M; 
    }
};

template<int M, int N>
int foo(S<M>);

} /* end of bar */

int main() {
    bar::S<> s;
    /* OK    { using namespace bar; return foo<42>(s) + foo<>(s); } // */
    /* NOK   { return foo<42>(s) + foo<>(s); } // */
    /* NOK   { using namespace bar; return bar::foo<42>(s) + bar::foo<>(s); } // */
    /* NOK */{ return bar::foo<42>(s) + bar::foo<>(s); } // */
}

我的問題是:為什么它使用using namespace bar; 使用不合格的名稱查找(請參閱帶有/* OK的行)? 雖然它不會在使用限定名稱查找 ( bar::foo<>() ) 或不using namespace的非限定名稱查找的變體中編譯(請參閱帶有/* NOK的行)?

命名空間bar包含對稱為foo的不同模板函數的聲明。

一個是template<int M, int N> int foo(S<M>); 最后聲明,每個S<M>都有一個聲明為友元函數。

好友 function 只能通過 ADL 找到。 因此,當您擁有bar::foo<42>(s)時,您只能調用免費的 function(其中42M的值,無法推導出N ,因此無法編譯)。

在 C++20 之前foo<42>(s)將被解釋為foo < 42 > (s)(foo < 42) > s具有等效的括號),因為<不被解釋為模板頭,因為查找for foo找不到模板。

添加時using namespace bar; ,查找foo會找到模板 function,因此foo<42>(s)被解析為模板化的 function 調用。 這最終會選擇在重載解析期間通過 ADL 找到的朋友 function。

這是通過在全局命名空間中添加 function 模板foo來解決的:

// Only for ADL purposes so `foo` is parsed as a template
template<typename> void foo() = delete;

int main() {
    bar::S<> s;
    return foo<42>(s) + foo<>(s);
}

暫無
暫無

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

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