【问题标题】:Template class with implicit conversion and operator overload but not inline具有隐式转换和运算符重载但不是内联的模板类
【发布时间】:2022-01-10 18:24:25
【问题描述】:

根据Implicit conversion when overloading operators for template classes 中的答案,我能够编写以下代码,并且运行良好(简化示例):

namespace my_library {

template <typename T>
struct Number {
    T n;

    inline Number(T n) : n(n) { }

    friend Number<T> operator+(const Number<T> &a, const Number<T> &b) {
        return Number<T>(a.n + b.n);
    }
};

}

int main() {
    return (int) (4 + my_library::Number<double>(3)).n; // returns 7
}

我要做的就是使operator+ 不在Number 的定义中内联(但保留在头文件中),而一切仍然以相同的方式工作 - 请参阅main 中的表达式功能。请注意,它要求将整数 4 隐式转换为 double,然后再转换为 Number&lt;double&gt;。我关注了链接到Binary operator overloading on a templated class 的评论,但该解决方案不起作用 - 重载的运算符不再匹配。有什么方法可以使这项工作并使操作员的主体在struct 定义之外? (不会使操作员界面复杂化或添加更多重载 - 在这些情况下,我宁愿将其保持内联。)

【问题讨论】:

    标签: c++ templates operator-overloading implicit-conversion


    【解决方案1】:

    你可以这样做:

    template <typename T>
    struct Number {
        // ...
        template <class U>
        friend Number<U> operator+(const Number<U> &a, const Number<U> &b);
    };
    
    template <typename U>
    Number<U> operator+(const Number<U> &a, const Number<U> &b) {
        return Number<U>(a.n + b.n);
    }
    

    在此示例中,operator+ 将成为所有 Number 特化的朋友,即使类型不匹配也是如此。这可能是比您预期的更广泛的友谊,但这是实现将operator+ 的定义移到Number 的定义之外的目标的最简单方法。请注意,如果未内联定义朋友,您将失去将其作为“隐藏朋友”的好处。 (隐藏的朋友只能通过依赖于参数的查找来找到,这意味着在大多数不打算使用它的情况下,编译器通常不必将其视为候选函数。)

    如果您希望operator+ 的每个特化只成为类型匹配的特定Number 特化的朋友,则更复杂。您必须转发声明operator+ 模板以防止friend 声明声明非模板函数,并且您还必须转发声明Number 以便它可以在operator+ 中使用前向声明:

    template <typename T> struct Number;
    
    template <typename T>
    Number<T> operator+(const Number<T>&, const Number<T>&);
    
    template <typename T>
    struct Number {
        // ...
        friend Number<T> operator+<>(const Number<T>&, const Number<T>&);
    };
    
    template <typename T>
    Number<T> operator+(const Number<T> &a, const Number<T> &b) {
        return Number<T>(a.n + b.n);
    }
    

    【讨论】:

    • 不起作用 - “朋友声明声明了一个非模板函数”和运算符的链接器错误。
    • @Detheroc 哪个不行?
    • 第一个与运算符不匹配,第二个有我提到的错误。
    • 但不适用于42 + Number&lt;int&gt;(42)
    • @Detheroc 友元函数的情况很特殊。它无法完成,因为它没有语法,并且您用于定义模板的常用语法不起作用的原因是您示例中的 operator+ 实际上不是模板;它只是一个单独的非模板函数,每次 Number 用不同的 T 实例化时都会生成。
    猜你喜欢
    • 2012-02-11
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    相关资源
    最近更新 更多