Tool/software: TI C/C++ Compiler
I'm validating 18.1.4.LTS on our code base and I'm getting a false diagnostic:
>> Compilation failure ServoLibrary/motionControl/brake/subdir_rules.mk:9: recipe for target 'ServoLibrary/motionControl/brake/Brake.obj' failed "C:\devel\Servo\ServoApplication\ServoLibrary\hal\TMS320C28346\include\..\..\..\service\math\Absolute.h", line 74: error #1581-D: "service::math::Absolute<T> operator+(const service::math::Relative<T> &, const service::math::Absolute<T> &)" declares a non-template function -- add <> to refer to a template instance "C:\devel\Servo\ServoApplication\ServoLibrary\hal\TMS320C28346\include\..\..\..\service\math\Absolute.h", line 90: error #1581-D: "service::math::Absolute<T> operator-(const service::math::Relative<T> &, const service::math::Absolute<T> &)" declares a non-template function -- add <> to refer to a template instance "C:\devel\Servo\ServoApplication\ServoLibrary\hal\TMS320C28346\include\..\..\..\service\math\Relative.h", line 130: error #1581-D: "service::math::Absolute<T> operator+(const service::math::Absolute<T> &, const service::math::Relative<T> &)" declares a non-template function -- add <> to refer to a template instance "C:\devel\Servo\ServoApplication\ServoLibrary\hal\TMS320C28346\include\..\..\..\service\math\Relative.h", line 160: error #1581-D: "service::math::Absolute<T> operator-(const service::math::Absolute<T> &, const service::math::Relative<T> &)" declares a non-template function -- add <> to refer to a template instance 4 errors detected in the compilation of ...
Apparently, the compiler thinks that non-inline friends of a template class must be templates themselves. However in this case the friends are defined inline in a partner class and the friend declaration exists to enable argument dependent lookup in cases where one of the two arguments must be constructed implicitly from a compatible type.
Here is the relevant code minus comments (to make it more compact):
#ifndef _SERVICE_MATH_ABSOLUTE_H_ #define _SERVICE_MATH_ABSOLUTE_H_ namespace service { namespace math { template <typename> struct Relative; template <typename T> struct Absolute { Absolute(T const& rValue) : mValue(rValue) {} friend Absolute<T> operator +(Absolute<T> const& rLSummand, Relative<T> const& rRSummand) { return rLSummand.mValue + rRSummand.mValue; } // error #1581 friend Absolute<T> operator +(Relative<T> const&, Absolute<T> const&); friend Absolute<T> operator -(Absolute<T> const& rMinuend, Relative<T> const& rSubtrahend) { return rMinuend.mValue - rSubtrahend.mValue; } // error #1581 friend Absolute<T> operator -(Relative<T> const&, Absolute<T> const&); friend Relative<T> operator -(Absolute<T> const& rMinuend, Absolute<T> const& rSubtrahend) { return rMinuend.mValue - rSubtrahend.mValue; } friend bool operator ==(Absolute<T> const& rLhs, Absolute<T> const& rRhs) { return rLhs.mValue == rRhs.mValue; } friend bool operator !=(Absolute<T> const& rLhs, Absolute<T> const& rRhs) { return rLhs.mValue != rRhs.mValue; } friend bool operator <(Absolute<T> const& rLhs, Absolute<T> const& rRhs) { return rLhs.mValue < rRhs.mValue; } friend bool operator <=(Absolute<T> const& rLhs, Absolute<T> const& rRhs) { return rLhs.mValue <= rRhs.mValue; } friend bool operator >(Absolute<T> const& rLhs, Absolute<T> const& rRhs) { return rLhs.mValue > rRhs.mValue; } friend bool operator >=(Absolute<T> const& rLhs, Absolute<T> const& rRhs) { return rLhs.mValue >= rRhs.mValue; } T mValue; }; } /* namespace math */ } /* namespace service */ #endif /* _SERVICE_MATH_ABSOLUTE_H_ */
#ifndef _SERVICE_MATH_RELATIVE_H_ #define _SERVICE_MATH_RELATIVE_H_ namespace service { namespace math { template <typename> struct Absolute; template <typename> struct Relative; template <typename T> inline Relative<T> operator %(Relative<T> const& rDivident, Relative<T> const& rQuotient) { return rDivident.mValue % rQuotient.mValue; } template <typename T> struct Relative { Relative(T const& rValue) : mValue(rValue) {} friend Relative<T> operator +(Relative<T> const& rOp) { return rOp; } friend Relative<T> operator -(Relative<T> const& rOp) { return - rOp.mValue; } // error #1581
friend Absolute<T> operator +(Absolute<T> const&, Relative<T> const&); friend Absolute<T> operator +(Relative<T> const& rLSummand, Absolute<T> const& rRSummand) { return rLSummand.mValue + rRSummand.mValue; } friend Relative<T> operator +(Relative<T> const& rLSummand, Relative<T> const& rRSummand) { return rLSummand.mValue + rRSummand.mValue; } // error #1581
friend Absolute<T> operator -(Absolute<T> const&, Relative<T> const&); friend Absolute<T> operator -(Relative<T> const& rMinuend, Absolute<T> const& rSubtrahend) { return rMinuend.mValue - rSubtrahend.mValue; } friend Relative<T> operator -(Relative<T> const& rMinuend, Relative<T> const& rSubtrahend) { return rMinuend.mValue - rSubtrahend.mValue; } friend Relative<T> operator *(Relative<T> const& rLFactor, Relative<T> const& rRFactor) { return rLFactor.mValue * rRFactor.mValue; } friend Relative<T> operator /(Relative<T> const& rDivident, Relative<T> const& rQuotient) { return rDivident.mValue / rQuotient.mValue; } friend Relative<T> operator %(Relative<T> const& rDivident, Relative<T> const& rDivisor) { return operator %<T>(rDivident, rDivisor); } friend bool operator ==(Relative<T> const& rLhs, Relative<T> const& rRhs) { return rLhs.mValue == rRhs.mValue; } friend bool operator !=(Relative<T> const& rLhs, Relative<T> const& rRhs) { return rLhs.mValue != rRhs.mValue; } friend bool operator <(Relative<T> const& rLhs, Relative<T> const& rRhs) { return rLhs.mValue < rRhs.mValue; } friend bool operator <=(Relative<T> const& rLhs, Relative<T> const& rRhs) { return rLhs.mValue <= rRhs.mValue; } friend bool operator >(Relative<T> const& rLhs, Relative<T> const& rRhs) { return rLhs.mValue > rRhs.mValue; } friend bool operator >=(Relative<T> const& rLhs, Relative<T> const& rRhs) { return rLhs.mValue >= rRhs.mValue; } T mValue; }; #pragma diag_pop } /* namespace math */ } /* namespace service */ #endif /* _SERVICE_MATH_RELATIVE_H_ */