C ++ implicit conversion to user statement for template classes

I have a structure template A<x> and + with int .

 #include <iostream> template<int x> struct A{ int a; }; template<int x> int operator+(A<x> a, int b){ return a.a+b; } 

I created a structure template B<x> , which can be converted to A<x> .

 template<int x> struct B{ int b=3; operator A<x>(){ return {b+10}; } }; 

Now I want B<x> be converted to A<x> when calling B<x> + int .

 int main(){ std::cout<<(A<12>{9}+10)<<std::endl;//OK std::cout<<(B<12>{9}+10)<<std::endl;//Error return 0; } 

I read Implicit conversion when overloading operators for template classes and wrote

 template<int x> struct B{ int b=3; operator A<x>(){ return {b+10}; } friend int operator+(A<x> a, int b); }; 

but this did not work because the declared friend int operator+(A<x> a, int b) does not match template<int x> int operator+(A<x> a, int b) .

I read C ++ - how to declare a friend a function template for a class template and created a friend declaration template, but it did not work because the template parameter couldn’t be output.

Of course, I could write the + operator for A and B, but I have dozens of operators, and I don't want to do this.

What is the right way to do this?

+5
source share
4 answers

I tried to edit Barrys using the following (executable) code that produces the correct output, but was rejected there.

I will add it here if anyone is interested.

 #include <iostream> template <int x> struct A { int a; friend int operator+(A a, int b) { return aa + b; } }; template <int x> struct B { int b; operator A<x>() { return {b+10}; } friend int operator+(A<x>, int ); }; int main() { std::cout << (A<12>{9} + 10) << std::endl; std::cout << (B<12>{9} + 10) << std::endl; } 

What seal

 19 29 
0
source

Considering two ways to create a non-member operator+ for A , we can either make it a function template:

 template <int x> int operator+(A<x>, int); 

which will not match B<x> , because we simply draw the output of a template that does not allow conversion.

Or we can make it a friend without a template:

 template <int x> struct A { friend int operator+(A a, int ); }; 

which will also not match B<x> , because a name lookup will not consider this function. If, say, we do not say:

 template <int x> struct B { friend int operator+(A<x>, int ); // NB: not a template }; 

Now the original non-template operator+ will be considered, the conversion will be performed as desired, and your code will print 29.

+5
source

You may have already seen this, but at least you can still make an explicit cast, and this can be useful:

 int main(){ std::cout<<(A<12>{9}+10)<<std::endl; // prints 19 std::cout<<(static_cast<A<12>>(B<12>{9})+10)<<std::endl; // prints 29 return 0; } 
+1
source

I hope this can help you.

I have a template friend operator+

Produced from A<x> and compiled, but after calling friend operator+ variable a was uninit, so I got immediate values. You have to set a somehow, and this seems to work.

 #include <iostream> template<int x> struct A { int a{x}; }; template<int x> int operator+(A<x> a, int b) { return a.a+b; } template<int x> struct B : A<x> { int b; template<int U> friend int operator+(A<U> a, int b); }; int main(void) { std::cout<< (A<20>{}+10)<<std::endl; // prints 30 std::cout<< (B<10>{}+10)<<std::endl; // prints 20 return 0; } 
0
source

Source: https://habr.com/ru/post/1270949/


All Articles