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
,我想给powerpow(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
的名称空间相同。