gpt4 book ai didi

c++ - 最烦人的 friend ?友化专门的自由函数模板会引发编译错误(重载方法时)

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:54:41 24 4
gpt4 key购买 nike

代码

我将问题简化为这个例子(粘贴为一个 block 以便于编译)

/// \brief The free-function template,
/// which is overloading a method with the same name in AbstractA below.
template <class T>
inline const T overloadedMethod(const T& lhs, const T& rhs)
{
return T(lhs.value+rhs.value);
}

/// \brief AbstractA class
class AbstractA
{
public:
AbstractA (int aVal):
value(aVal)
{}


inline const AbstractA overloadedMethod(const AbstractA &rhs) const
{
return AbstractA(value+rhs.value);
}

protected:
int value;
};

/// \brief A class, deriving from AbstractA,
/// and friending the free-function template.
class A : public AbstractA
{
friend const A overloadedMethod <A>(const A& lhs, const A& rhs);
/// This one gives me compilation error
//template<class T> friend const T overloadedMethod(const T& lhs, const T& rhs);
/// This one would be okay

public:
A (int aVal):
AbstractA(aVal)
{}
};

int main()
{
A a1(1), a2(2);
overloadedMethod(a1, a2);

return 0;
}

详情

基本上,我试过的编译器(VS 2010 和 G++ 4.7.2)给我一个错误

friend const A overloadedMethod <A>(const A& lhs, const A& rhs);

他们似乎认为我正在声明一个名为overloadedMethod 的数据成员。

在以下情况下不会引发编译错误:

  • 我把自由函数模板的非特化版本作为 friend (代码注释行)
  • 我从类 AbstractA 中删除了成员函数 overloadedMethod()

问题

我无法解释语言的这种行为,所以我的问题是:

  • 导致此错误的 C++ 规则是什么? (为什么编译器会认为我在这里声明了一个数据成员?)
  • 你知道背后的原理吗? (我特别想知道为什么如果我从 AbstractA 类中删除 overloadedMethod() 似乎有效。或者它是 UB 吗?)

最佳答案

首先,你的基本前提friend声明是正确的:

[C++11: 14.5.4/1]: A friend of a class or class template can be a function template or class template, a specialization of a function template or class template, or an ordinary (non-template) function or class. For a friend function declaration that is not a template declaration:

  • if the name of the friend is a qualified or unqualified template-id, the friend declaration refers to a specialization of a function template, otherwise
  • if the name of the friend is a qualified-id and a matching non-template function is found in the specified class or namespace, the friend declaration refers to that function, otherwise,
  • if the name of the friend is a qualified-id and a matching function template is found in the specified class or namespace, the friend declaration refers to the deduced specialization of that function template (14.8.2.6), otherwise,
  • the name shall be an unqualified-id that declares (or redeclares) an ordinary (non-template) function.

[ Example:

template<class T> class task;
template<class T> task<T>* preempt(task<T>*);
template<class T> class task {
friend void next_time();
friend void process(task<T>*);
friend task<T>* preempt<T>(task<T>*);
template<class C> friend int func(C);
friend class task<int>;
template<class P> friend class frd;
};

[..] —end example ]

您可能会遇到问题,因为名称 overloadedMethod从基类隐藏全局类——不考虑不同的参数列表,以及基名不代表模板的事实:

[C++11: 3.4.1/9]: Name lookup for a name used in the definition of a friend function (11.3) defined inline in the class granting friendship shall proceed as described for lookup in member function definitions. If the friend function is not defined in the class granting friendship, name lookup in the friend function definition shall proceed as described for lookup in namespace member function definitions.

[C++11: 3.4.1/10]: In a friend declaration naming a member function, a name used in the function declarator and not part of a template-argument in the declarator-id is first looked up in the scope of the member function’s class (10.2). If it is not found, or if the name is part of a template-argument in the declarator-id, the look up is as described for unqualified names in the definition of the class granting friendship.

在这种情况下永远不会触发“如果未找到”子句。

在 GCC 4.8.1 中 this results in the following diagnostic :

error: field ‘overloadedMethod’ has incomplete type

我确定此诊断的具体内容略有错误 — 通过应用 template-parameter-list <A>,您基本上混淆了编译器到它不认为是模板的东西。

你无法解决这个问题,even by qualifying the friend declaration :

friend const A ::overloadedMethod<A>(const A& lhs, const A& rhs);

以下确实有效:

friend auto ::overloadedMethod<A>(const A&, const A&) -> const A;

但我认为,根据上述规则,这实际上是一个编译器错误。

关于c++ - 最烦人的 friend ?友化专门的自由函数模板会引发编译错误(重载方法时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18099166/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com