我有一个用户构建的类型T
,我想为其赋予一种含义pow(T1, T2)
。
然后,在模板代码中,我希望能够编写std::pow(a, b)
,然后如果a, b
恰好是双精度或浮点型,它将执行其始终会执行的操作,如果它们发生了的类型为T
,那么我想调用我的重载。
我该怎么做?
我可以给我的类型一个pow
运算符,但是如何区分std::pow
和pow
运算符呢?
答案 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
}