[英]Class A member template function declared as friend in class B can't access private members of class A (Clang only)
請查看此代碼段。 我知道它沒有多大意義,它只是為了說明我遇到的問題:
#include <iostream>
using namespace std;
struct tBar
{
template <typename T>
void PrintDataAndAddress(const T& thing)
{
cout << thing.mData;
PrintAddress<T>(thing);
}
private:
// friend struct tFoo; // fixes the compilation error
template <typename T>
void PrintAddress(const T& thing)
{
cout << " - " << &thing << endl;
}
};
struct tFoo
{
friend void tBar::PrintDataAndAddress<tFoo>(const tFoo&);
private:
int mData = 42;
};
struct tWidget
{
int mData = 666;
};
int main()
{
tBar bar;
bar.PrintDataAndAddress(tWidget()); // Fine
bar.PrintDataAndAddress(tFoo()); // Compilation error
return 0;
}
上面的代碼觸發以下錯誤:
source_file.cpp:10:3: 錯誤:'PrintAddress'是'tBar'PrintAddress(thing)的私有成員 ; source_file.cpp:42:6:注意:在實例化函數模板>特殊化'tBar :: PrintDataAndAddress'這里請求bar.PrintDataAndAddress(tFoo()); //編譯錯誤source_file.cpp:17:7:注意:聲明私有這里void PrintAddress(const T&thing)
但僅限於Clang ++。 GCC和MSVC很好用(您可以通過在http://rextester.com/l/cpp_online_compiler_clang中粘貼該代碼來快速測試)
似乎tBar::PrintDataAndAddress<tFoo>(const tFoo&)
使用與tFoo
相同的訪問tFoo
,在那里它是友好的。 我知道這是因為在tBar
與tFoo
建立tBar
解決這個問題。 如果tBar::PrintDataAndAddress
是非模板函數,問題也會消失。
我無法在標准中找到解釋此行為的任何內容。 我相信這可能是對14.6.5 - temp.inject的錯誤解釋,但我無法聲稱我已經閱讀了所有內容。
有沒有人知道Clang是否正確無法編譯上述代碼? 如果是這樣的話,你能引用相關的C ++標准文本嗎?
似乎要發生這個問題,被訪問的私有成員需要是模板功能。 例如,在上面的例子中,如果我們使PrintAddress成為非模板函數,代碼將編譯沒有錯誤。
在使用之前強制編譯器實例化tBar::PrintDataAndAddress<tFoo>
解決了這個問題。
int main()
{
tBar bar;
bar.PrintDataAndAddress(tWidget()); // Fine
auto x = &tBar::PrintDataAndAddress<tFoo>; // <= make it work....
bar.PrintDataAndAddress(tFoo()); // Now fine
return 0;
}
它似乎是一個編譯器promlem,因為它看起來非常相似:
在C ++中,為什么不能使用另一個類的模板類型來管理模板類成員函數?
要更精確一點......在行bar.PrintDataAndAddress(tFoo());
編譯器必須實現成員函數tBar::PrintDataAndAddress<tFoo>
,同時它必須解析友元聲明。 這是兩個單獨的步驟。 顯然,當編寫一個表達式時,編譯器不會按照嚴格順序執行此操作。 要強制編譯器首先通過訪問函數指針來實例化bar.PrintDataAndAddress(tFoo())
,這兩個步驟的順序正確。
嘗試在友元功能之前添加此功能
template <typename tFoo>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.