When defining a member function of a class template outside the class definition, the rules for template parameter repetition depend on the context:
::
(Qualified Name)You must repeat the template parameters because you're specifying the full type of the class template:
template<std::signed_integral T>
Ratio<T>& Ratio<T>::operator+=(...) { ... }
// ^^^^^^^^ Required: `Ratio<T>`
You must repeat the template parameters because the return type is outside the scope of the class:
template<std::signed_integral T>
Ratio<T>& Ratio<T>::operator+=(...) { ... }
// ^^^^^^^ Required: `Ratio<T>&`
You do not need to repeat them because:
The Ratio<T>::
prefix already establishes the scope.
The compiler can deduce Ratio inside the parameter list as Ratio<T>
(due to injected-class-name behavior).
template<std::signed_integral T>
Ratio<T>& Ratio<T>::operator+=(const Ratio& R) { ... }
// ^^^^^^ No `<T>` needed here
And why this happen ?
Ratio<T>
:template<std::signed_integral T>
struct Ratio {
Ratio& operator+=(const Ratio& R); // `Ratio` = `Ratio<T>`
};
::
and in the return type. However, after ::
, the compiler knows Ratio refers to Ratio<T>
.