这是我对this question的回答。
我发布的原始答案没有任何名称空间,它可以解决问题。但是,OP随后进行了编辑,声称如果类在名称空间中,则该解决方案不起作用。
我最初的反应是,只需在全局范围内或在using N::f;
(或任何其他函数)内部使用main()
,就可以使其工作。虽然确实是这样,但《 OP》(合理地)评论说这并不理想,我同意。
尽管如此,我仍然认为在没有N::f
的情况下调用using N::f;
而没有应该很好,但是令我惊讶的是,当我尝试以下操作时遇到了未定义的引用错误:
#include<iostream>
namespace N
{
template<class T>
class Class;
template<typename U, typename W>
Class<W> f (Class<U>& C, const Class<U>& D);
template<class T>
class Class
{
protected: // this could be private
T m_t;
public:
Class()
:
m_t(T())
{}
Class(T t)
:
m_t(t)
{}
T& getT()
{
return m_t;
}
template<typename U, typename W>
friend Class<W> f (Class<T>& C, const Class<T>& D)
{
C.m_t += D.m_t;
Class<W> R;
std::cout << R.m_t << std::endl; // I don't want this to be possible
return R;
}
};
}
int main()
{
N::Class<int> C(42), D(24);
std::cout << N::f<int, char>(C, D).getT() << std::endl;
}
error: undefined reference to N::Class<char> N::f<int, char>(N::Class<int>&, N::Class<int> const&)'
。
在这一点上,我继续尝试不同的编译器版本,发现上面的工作原理与没有namespace
with GCC < 6但没有not with GCC > 6的情况相同。 ICC 17似乎也在f
内部进行了受保护成员的访问,但没有选择ICC 18。 Clang永远不会捡起它。
预期的行为是什么?在没有using N::f;
的情况下,是否应该使定义可用于链接器?
编辑1:
为明确起见,我想保留预期的行为,即仅将f
限制为friend
的实例,使其匹配其参数(因此在示例{{1} }将从Class
到f
,而不是friend
)。