There are classes:

namespace gmath { template<class T, size_t s> class alignas(s) Vector3 : public _Vector<T> { public: template<class T1, size_t s> friend Vector3<T1, s> operator*(const Matrix3<T1, 64>& m, const Vector3<T1, s>& v); // здесь члены и другие объявления } template<class T, size_t s> class alignas(s) Matrix3 : public _Matrix<T, 3> { // здесь объявления и члены } } 

And there is an implementation of the above declared method:

 template<class T1, size_t s> Vector3<T1, s> gmath::operator*(const Matrix3<T1, 64>& m, const Vector3<T1, s>& v) { // здесь код } 

I am writing in Visual Studio 2017, when using this operator, the studio shows that it is overloaded and finds it. But when compiling I get this:

Error C2244 operator *: unable to match function definition to existing declaration

The error indicates exactly this method. MSDN said that when using templates, you should check the implementation mapping carefully ... I looked, I did not find it. Where to dig?

  • Definitely worth demonstrating the calling code. Is the implementation in the same broadcast unit as the ad? - free_ze
  • @free_ze yes, of course implementation in a single file. - Range
  • short answer: a friend template function (operator *) needs to be described directly in the class (its implementation) - acade
  • @acade below wrote the answer, see if you can tell why it works that way. - Range

1 answer 1

The code is played inaccurately. How did you manage to use the Matrix3 type before its announcement? The name of a template parameter cannot be reused as a parameter of a nested template. Your name s reused in such an incorrect way. In the internal friend declaration, you will have to use another name for the template parameter s .

As for the main problem, in order to define a member of the gmath namespace outside of the gmath namespace, gmath must first declare this member of the gmath namespace inside this namespace. Togo friend-ad that you made inside the class is not enough. It only refers to the “future” member of the gmath namespace, but does not create a visible declaration. Therefore, the compiler simply does not know what kind of function you are trying to define outside the gmath namespace.

You need to add an explicit declaration of your operator to your namespace.

 namespace gmath { template<class T, size_t s> class alignas(s) Matrix3 : public _Matrix<T, 3> { // ... }; template<class T, size_t s> class alignas(s) Vector3 : public _Vector<T> { template<class T1, size_t u> friend Vector3<T1, u> operator*(const Matrix3<T1, 64>& m, const Vector3<T1, u>& v); // ... }; template<class T, size_t s> Vector3<T, s> operator*(const Matrix3<T, 64>& m, const Vector3<T, s>& v); } 

Also outside of the gmath namespace, the gmath template is called gmath::Vector3 . This is exactly what it should be called in the return type of your function when using the "classical" syntax.

 template<class T, size_t s> gmath::Vector3<T, s> gmath::operator*(const Matrix3<T, 64>& m, const Vector3<T, s>& v) { // ... } 

For parameter declarations, this remark does not apply.

The question arises: why did you suddenly decide to define your operator outside the namespace? Why didn't you just define it inside and avoid almost all these unnecessary complications?

  • Thanks for the very detailed answer. I answer you: just experiments. Now I will know more about everything. - Range