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

时间:2017-08-17 04:24:33

标签: c++ templates operator-overloading c++14 friend-function

我有一个结构模板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>在调用A<x>时转换为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;
}

我读了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)不匹配。

我阅读了C++ - How to declare a function template friend for a class template并制作了朋友声明模板,但由于模板参数无法推断,因此无法正常使用。

当然我可以为A和B编写operator +,但是我有几十个操作员而且我不想这样做。

这样做的正确方法是什么?

4 个答案:

答案 0 :(得分:5)

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

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。

答案 1 :(得分:1)

您可能已经看过这个,但至少仍然可以进行显式演员,这可能很有用:

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

答案 2 :(得分:0)

我希望它可以帮助你。

我有模板的朋友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;
}

答案 3 :(得分:0)

我尝试使用以下(runnable)代码编辑Barrys回答,这会生成正确的输出,但在那里被拒绝了。

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

#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