模板 类 的用户定义运算符的 C++ 隐式转换

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

我有一个结构模板 A<x> 和一个 + 运算符 int.

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

我创建了一个结构模板 B<x>,它可以转换为 A<x>

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

现在我希望在调用B<x> + int时将B<x>转换为A<x>

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

我读了Implicit conversion when overloading operators for template classes写了

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

,但它不起作用,因为声明的 friend int operator+(A<x> a, int b)template<int x> int operator+(A<x> a, int b).

不匹配

看了做了朋友声明模板,但是没有成功,因为模板参数无法推导

当然我可以为 A 和 B 都写 operator+,但我有几十个运算符,我不想这样做。

正确的做法是什么?

希望对你有所帮助

我有模板朋友operator+

派生自 A<x> 并编译,但在调用 friend operator+ 变量后 a 是 uninit 所以我得到了立即值。您必须以某种方式设置 a,这似乎有效。

#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;
}

你可能已经看过了,但至少它仍然可以进行显式转换,而且它可能会有用:

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;
}

查看为 A 创建非成员 operator+ 的两种方法,我们可以将其设为函数模板:

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

这与 B<x> 不匹配,因为我们只是在进行模板推导,不允许转换。

或者,我们可以将其设为非模板友元:

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

也不会匹配 B<x> 因为名称查找不会考虑该函数。除非,也就是说,我们告诉它:

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

现在,会考虑我们原来的非模板operator+,按需要进行转换,你的代码打印29.

我试图用以下(可运行的)代码编辑巴里的答案,它产生了正确的输出,但在那里被拒绝了。

我会在这里添加它以防其他人好奇。

#include <iostream>

template <int x>
struct A {
    int a;
    friend int operator+(A a, int b) { return a.a + 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;
}

打印

19
29