Friend function with a definition - template or non-template?

谁都会走 提交于 2019-12-10 16:59:34

问题


Suppose we have the following code:

template<class T> struct S;
template<class T> void operator++(S<T>);

template<class T> struct S {
    friend void operator++(S);
};

template<class T>
void operator++(S<T>) {}

int main() {
    S<int> s;
    ++s;
}

This will compile but won't link, because the friend declaration introduces a non-template operator++, that has never been defined.

This FAQ answer reads (bold is mine):

The solution is to convince the compiler while it is examining the class body proper that the operator++ function is itself a template. There are several ways to do this;

The first way is to add <> into the friend declaration, and I'm not considering it here. The second is "to define the friend function within the class body":

template<class T> struct S {
    friend void operator++(S) { }
};

The quote suggests that void operator++(S) is now a function template and not a non-template function. Is it?


回答1:


It is not a template, because its declaration is not that of a template (even though it appears inside a template declaration itself).

[temp.friend] (emphasis mine)

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 a 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 ([temp.deduct.decl]), otherwise,

  • the name shall be an unqualified-id that declares (or redeclares) a 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;
};

Here, each specialization of the task class template has the function next_­time as a friend; because process does not have explicit template-arguments, each specialization of the task class template has an appropriately typed function process as a friend, and this friend is not a function template specialization; because the friend preempt has an explicit template-argument T, each specialization of the task class template has the appropriate specialization of the function template preempt as a friend; and each specialization of the task class template has all specializations of the function template func as friends. Similarly, each specialization of the task class template has the class template specialization task<int> as a friend, and has all specializations of the class template frd as friends.  — end example ]

While examples are non-normative, the one in the quote clarifies the intent of the preceding normative text. Since the friend operator declaration is not a template declaration, the text in bold applies. It therefore declares a non-template function.




回答2:


With

template<class T> struct S {
    friend void operator++(S s) { }
};

operator ++ is no longer template.

For more regular function (operator usage is a little different than function), it might allow deduction:

template<class T> struct S {
    S(T t);
    friend void foo(S lhs, S rhs) { }
};

template <typename T>
void bar(S<T> s, T t)
{
    foo(s, t);   // would not work if foo was template, would require foo<T>(s, t);
    foo(s, {t}); // would not work if foo was template, would require foo<T>(s, {t});
}


来源:https://stackoverflow.com/questions/58837772/friend-function-with-a-definition-template-or-non-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!