C ++:如何为用户类型重载pow?

时间:2018-11-02 20:01:36

标签: c++ operator-overloading

我有一个用户构建的类型T,我想为其赋予一种含义pow(T1, T2)

然后,在模板代码中,我希望能够编写std::pow(a, b),然后如果a, b恰好是双精度或浮点型,它将执行其始终会执行的操作,如果它们发生了的类型为T,那么我想调用我的重载。

我该怎么做?

我可以给我的类型一个pow运算符,但是如何区分std::powpow运算符呢?

3 个答案:

答案 0 :(得分:5)

不允许将函数重载到std名称空间中。一个典型的解决方案是在与自定义类型相同的名称空间中声明函数,例如

namespace my_code
{
    struct foo {};

    foo pow(foo base, int power)
    {
        // code here
    }
}

然后在要对事物使用pow的函数中,添加using std::pow。然后,您可以像这样写代码

void bar()
{
    using std::pow;
    //...
    auto a = pow(10,3);
    //...
    auto b = pow(foo{}, 3);

}

并且行pow(10,3)将选择函数的std版本,而pow(foo, 3)将通过argument dependent lookup找到您的重载。

答案 1 :(得分:0)

不允许将名称添加到std命名空间。您唯一可以做的就是添加专业化。如果您愿意忽略这一点(许多人愿意!),最简单的解决方案是将此重载添加到命名空间std中。

一种完全一致的解决方案是将重载添加到一个可见的命名空间中,并且比每当您计划调用可用的pow版本之一时都要这样做:

using std::pow;

pow(a, b);

然后,如果a和b恰好是std::pow支持的类型,它将被调用,否则,您的重载将发生。

答案 2 :(得分:0)

您不能直接超载std::pow。该标准禁止向std命名空间中的函数添加新的重载。

您可以做的是使用ADL选择所需的pow函数,类似于人们经常添加swap重载的方法:

namespace my_namespace {

struct my_type {
    explicit my_type(double d) : my_num{d} {}
    double my_num;
};

my_type pow(const my_type& a, const my_type& b) {
    std::cout << "my_namespace::pow(my_type, my_type) called\n";
    return my_type{std::pow(a.my_num, b.my_num)};
}

}

template <typename T>
void foo() {
    using std::pow;
    pow(T{2}, T{10});
}

int main() {
    foo<float>(); // calls std::pow
    foo<my_namespace::my_type>(); // calls my_namespace::pow
}

Live Demo

相关问题