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

C++ C++;:如何为用户类型重载pow?,c++,operator-overloading,C++,Operator Overloading,我有一个用户构建的类型T,我想给powerpow(T1,T2)的概念赋予意义 然后,在模板化代码中,我希望能够编写std::pow(a,b),然后如果a,b恰好是双精度或浮点数,它将执行它通常执行的操作,如果它们恰好是T类型,那么我希望调用我的重载 我该怎么做 我可以给我的类型一个pow-运算符,但是我如何区分std::pow和pow-运算符?不允许将函数重载到std名称空间中。一个典型的解决方案是在与自定义类型相同的命名空间中声明函数,如 namespace my_code { str

我有一个用户构建的类型
T
,我想给power
pow(T1,T2)
的概念赋予意义

然后,在模板化代码中,我希望能够编写
std::pow(a,b)
,然后如果
a,b
恰好是双精度或浮点数,它将执行它通常执行的操作,如果它们恰好是
T
类型,那么我希望调用我的重载

我该怎么做


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

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

namespace my_code
{
    struct foo {};

    foo pow(foo base, int power)
    {
        // code here
    }
}
然后在函数中使用
pow
在对象上添加
使用std::pow
。这使您可以像这样编写代码

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

}

pow(10,3)
将选择函数的
std
版本,而
pow(foo,3)
将找到您的重载。

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

namespace my_code
{
    struct foo {};

    foo pow(foo base, int power)
    {
        // code here
    }
}
然后在函数中使用
pow
在对象上添加
使用std::pow
。这使您可以像这样编写代码

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

}

pow(10,3)
将选择函数的
std
版本,而
pow(foo,3)
将查找您的重载。

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

一个完全一致的解决方案是将重载添加到一个可见名称空间中,而不是在您计划调用一个可用的
pow
版本时,执行以下操作:

using std::pow;

pow(a, b);

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

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

一个完全一致的解决方案是将重载添加到一个可见名称空间中,而不是在您计划调用一个可用的
pow
版本时,执行以下操作:

using std::pow;

pow(a, b);

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

您不能直接重载
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
}
名称空间我的名称空间{
结构我的类型{
显式my_类型(双d):my_num{d}{
加倍我的数量;
};
我的类型功率(常数我的类型&a,常数我的类型&b){

std::cout不能直接重载
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
}
命名空间my\u命名空间{
结构我的类型{
显式my_类型(双d):my_num{d}{
加倍我的数量;
};
我的类型功率(常数我的类型&a,常数我的类型&b){

std::cout如果您的
pow
函数在全局命名空间中,您可以将其消歧为
::pow(T1,T2)
。否则如果定义了运算符,比如在
T1
类中,它将是
T1::pow(T1,T2);
如果
pow
函数在全局命名空间中,您可以将其消歧为
::pow(T1,T2)
。否则,如果操作符是在
T1
类中定义的,那么它将是
T1::pow(T1,T2);
不必位于全局名称空间中,与
foo
的名称空间相同。但不必位于全局名称空间中,与
foo
的名称空间相同。