Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ implicit conversion on user-defined operator for template classes

I have a struct template A<x> and a + operator 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 struct template B<x>, which is convertible to A<x>.

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

Now I want B<x> to 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 it didn't 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 function template friend for a class template and made friend declaration template, but it didn't work because the template parameter couldn't be deduced.

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

What is the correct way to do this?

like image 452
eivour Avatar asked Aug 17 '17 04:08

eivour


People also ask

How many types are there in user-defined conversion from class to class?

There are two types of user-defined conversions: Conversion constructors and conversion functions.

What is an implicit conversion function?

An implicit conversion sequence is the sequence of conversions required to convert an argument in a function call to the type of the corresponding parameter in a function declaration. The compiler tries to determine an implicit conversion sequence for each argument.

What is user-defined conversion?

For more information, see Standard Conversions. User-defined conversions perform conversions between user-defined types, or between user-defined types and built-in types. You can implement them as Conversion constructors or as Conversion functions.

What is an implicit type conversion in C++?

Implicit type conversion also known as automatic type conversion is carried out by the compiler without the need for a user-initiated action. It takes place when an expression of more than one data type is present which in such an instance type conversion takes place to avoid data loss.


1 Answers

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

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

which won't match B<x> because we're just doing template deduction, which doesn't allow for conversions.

Or, we can make it a friend non-template:

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

which also won't match B<x> because name lookup won't consider that function. Unless, that is, we tell it to:

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

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

like image 189
Barry Avatar answered Oct 29 '22 02:10

Barry