将c ++数学函数扩展到非基本类型

时间:2015-11-16 03:33:05

标签: c++ math overloading

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

例如。下面的关键是能够对基本和myType使用bar()。对于myType而言不是foo(),对于基本类型则不是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
}

2 个答案:

答案 0 :(得分:4)

首先,存在依赖于参数的查找(ADL,a.k.a.KönigLookup),它在其参数的命名空间中搜索函数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<T>类型。
  • if (X) {return true;} else {return false};可以写得小得多return X;

答案 1 :(得分:1)

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