请查看此代码段。我知道这没有多大意义,只是为了说明我遇到的问题:
#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: error: 'PrintAddress' is a private member of 'tBar' PrintAddress(thing); source_file.cpp:42:6: note: in instantiation of function template >specialization 'tBar::PrintDataAndAddress' requested here bar.PrintDataAndAddress(tFoo()); // Compilation error source_file.cpp:17:7: note: declared private here void PrintAddress(const T& thing)
但仅在 Clang++ 中。 GCC 和 MSVC 都可以(你可以通过将代码粘贴到 http://rextester.com/l/cpp_online_compiler_clang 中来快速测试)
似乎 tBar::PrintDataAndAddress<tFoo>(const tFoo&)
使用与 tFoo
相同的访问权限,在那里它是 friend 。我知道这一点,因为在 tFoo
中与 tBar
成为 friend 可以解决此问题。如果 tBar::PrintDataAndAddress
是非模板函数,问题也会消失。
我无法在标准中找到任何解释此行为的内容。我认为这可能是对 14.6.5 - temp.inject 的错误解释,但我不能声称我已经阅读了所有内容。
有谁知道 Clang 未能编译上述代码是否正确?如果是这样,您能否引用相关的 C++ 标准文本?
似乎要发生这个问题,被访问的私有(private)成员需要是一个模板函数。例如,在上面的例子中,如果 我们将 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;
}
这似乎是一个编译器问题,因为它看起来与此非常相似:
更准确一点...在 bar.PrintDataAndAddress(tFoo());
行中编译器必须实例化成员函数 tBar::PrintDataAndAddress<tFoo>
同时它必须解决 friend 声明。那是内部两个单独的步骤。显然,当用一个表达式编写时,编译器并没有按照严格的顺序执行此操作。强制编译器实例化 bar.PrintDataAndAddress(tFoo())
首先通过访问函数指针这两个步骤的顺序是正确的。
关于c++ - 在 B 类中声明为友元的 A 类成员模板函数无法访问 A 类的私有(private)成员(仅限 Clang),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40350327/