【问题标题】:extending c++ math functions to non fundamental types将 c++ 数学函数扩展到非基本类型
【发布时间】:2015-11-16 03:33:04
【问题描述】:

我想延长?或重载?(不太确定叫什么) double 和其他基本类型使用的 sqrt() 函数,因此我自己的类可以使用它。这里称为“myType”。我将编写函数 sqrt() 以用于其参数是 myType 的情况。我希望 sqrt() 在用于基本类型时保持不变。这样我就可以编写一个涵盖这两种情况的模板。

例如。下面的关键是能够将 bar() 用于基本类型和 myType。不是 foo() 用于 myType 和 bar() 用于基本类型。这可以干净地完成吗?提前感谢您的帮助。

#include <math.h>

using namespace std;

class myType
{
public:
    myType() {
    }
    double sqrt()
    {
        return  4;//just to return something
    }
};

template<typename T> bool bar(T in)
{
    if (sqrt(in) == 4) {// handels int and all sorts of other types but not my type
        return true;
    }
    return false;
}

template<typename T> bool foo(T in)
{
    if (in.sqrt() == 4) { //handles myType
        return true;
    }
    return false;
}

int main() {
    double y = 3;
    bar(y);//This is great

    myType x;
    //bar(x);//this is the line I want to write
    foo(x);//stuck doing this
}

【问题讨论】:

    标签: c++ math overloading


    【解决方案1】:

    首先,有依赖于参数的查找(ADL,又名 König Lookup),它在其参数的命名空间中搜索函数 foo()。因此,如果您在命名空间my 中定义您的类,您可以在该命名空间中定义一个函数sqrt(),即使在非限定上下文中调用它也会自动找到。

    其次,为了使您的模板函数具有通用性,您需要启用 ADL。但是,如果您将它与基本类型一起使用,它仍然不会在命名空间std 内查看。因此,给编译器一个提示,std::sqrt 可以在函数中使用。

    示例(草图):

    namespace my {
        struct number;
        number sqrt(number const&);
    }
    
    template<typename scalar>
    scalar
    sym_sqrt(scalar const& s) {
        using std::sqrt;
        if (s < 0) {
            return -sqrt(-s);
        else
            return sqrt(s);
    }
    
    int main() {
        float m = ...;
        std::cout << sym_sqrt(m);
    
        my::number n = ...;
        std::cout << sym_sqrt(n);
    }
    

    注意事项

    • 我没有using namespace std;。这既不是必要的,尤其是您班级的用户也不需要。现在就改掉这个习惯吧!
    • 关于措辞,您不能扩展函数,但可以将重载添加到现有重载。
    • 如果您使用古老的编译器,您可能会遇到 sqrt 是宏的问题。那就升级编译器吧。
    • 请注意,sqrt() 在您的尝试中被定义为成员函数,这是一个完全不同的野兽。将其保留为类似于现有版本的免费功能。一般来说,不要盲目地将东西放入类中。使用普通函数有充分的理由。特别是在数学意义上表示函数的数学函数(没有副作用,没有外部依赖性)实际上可以很好地放入函数中。
    • std::sqrt() 已经为非基本类型重载,即不同的 std::complex&lt;T&gt; 类型。
    • if (X) {return true;} else {return false}; 可以写成更小的return X;

    【讨论】:

    • 出于好奇,我检查了编辑。 @Toby,我没有意识到您的编辑是答案的重要组成部分。非常感谢!
    【解决方案2】:

    我认为您无法使std::sqrt 与您的用户定义类型一起工作(除非它们可以使用转换运算符转换为基本数据类型)。但是您可以编写自己的函数,默认重定向到std::sqrt,并将其专门用于您的用户定义类型。然后在您的代码中使用该函数而不是 std::sqrt

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-09
      • 2022-07-12
      • 2012-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      相关资源
      最近更新 更多