将 C++ 数学函数扩展到非基本类型
extending c++ math functions to non fundamental types
我要延期?或重载?(不太确定如何称呼它)double 和其他基本类型使用的 sqrt() 函数,因此它可以由我自己使用 class。这里叫"myType"。当它的参数是 myType 时,我将编写函数 sqrt() 的代码。我希望 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
}
我认为您无法做任何事情来使 std::sqrt
使用您的用户定义类型(除非可以使用转换运算符将它们转换为基本数据类型)。但是您可以编写自己的默认重定向到 std::sqrt
的函数,并将其专门用于您的用户定义类型。然后在您的代码中使用该函数而不是 std::sqrt
.
首先,有参数依赖查找(ADL,a.k.a。König Lookup)在其参数的命名空间中搜索函数 foo()
。因此,如果您在命名空间 my
中定义 class,您可以在该命名空间中定义一个函数 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;
。这既不是必需的,尤其是您 class 的用户也不需要这样做。现在改掉这个习惯!
- 关于措辞,您不能扩展函数,而是在现有重载的基础上添加重载。
- 如果您使用古老的编译器,您可能会遇到
sqrt
作为宏的问题。那就升级编译器吧
- 请注意,您尝试中的
sqrt()
被定义为成员函数,这是一个完全不同的野兽。将其保留为与现有版本类似的免费功能。一般情况下,不要盲目的把东西放到classes。使用普通函数有充分的理由。特别是在数学意义上表示函数(没有副作用,没有外部依赖性)的数学函数实际上很好地放入了函数中。
std::sqrt()
已经为非基本类型重载,即对于不同的 std::complex<T>
类型。
if (X) {return true;} else {return false};
可以写得更小如 return X;
.
我要延期?或重载?(不太确定如何称呼它)double 和其他基本类型使用的 sqrt() 函数,因此它可以由我自己使用 class。这里叫"myType"。当它的参数是 myType 时,我将编写函数 sqrt() 的代码。我希望 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
}
我认为您无法做任何事情来使 std::sqrt
使用您的用户定义类型(除非可以使用转换运算符将它们转换为基本数据类型)。但是您可以编写自己的默认重定向到 std::sqrt
的函数,并将其专门用于您的用户定义类型。然后在您的代码中使用该函数而不是 std::sqrt
.
首先,有参数依赖查找(ADL,a.k.a。König Lookup)在其参数的命名空间中搜索函数 foo()
。因此,如果您在命名空间 my
中定义 class,您可以在该命名空间中定义一个函数 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;
。这既不是必需的,尤其是您 class 的用户也不需要这样做。现在改掉这个习惯! - 关于措辞,您不能扩展函数,而是在现有重载的基础上添加重载。
- 如果您使用古老的编译器,您可能会遇到
sqrt
作为宏的问题。那就升级编译器吧 - 请注意,您尝试中的
sqrt()
被定义为成员函数,这是一个完全不同的野兽。将其保留为与现有版本类似的免费功能。一般情况下,不要盲目的把东西放到classes。使用普通函数有充分的理由。特别是在数学意义上表示函数(没有副作用,没有外部依赖性)的数学函数实际上很好地放入了函数中。 std::sqrt()
已经为非基本类型重载,即对于不同的std::complex<T>
类型。if (X) {return true;} else {return false};
可以写得更小如return X;
.