[英]Overloading function templates in namespace std
此处讨论了关于 function 特化的讨论: C++20 中不再允许在 std 中对程序定义类型进行 function 模板的特化吗?
原则上我理解,最好是重载而不是专门化。 但是你如何正确地重载一个标准的 function 模板呢? 规范的答案似乎是:只需在您的自定义命名空间中重载,然后 ADL 就会启动。但是,如果涉及基本类型,这不起作用。 非工作示例:
#include <cmath>
namespace X {
class Y { };
Y sqrt(Y);
double foo(double x) { return sqrt(x); }
}
该示例只会在没有 Y 的 sqrt 声明的情况下编译。可以通过在命名空间 std 中重载来解决此问题:
#include <cmath>
namespace X {
class Y { };
}
namespace std { X::Y sqrt(X::Y); }
namespace X {
double foo(double x)
{
return sqrt(x);
}
}
这段代码正是我想做的。 但是我不确定标准是否允许这种重载。 在 cppreference 我没有找到指向这个方向的提示。 虽然 Walter E. Brown 的这篇论文提出重载作为专业化的替代方案,但我不确定上面的示例是否正确使用它(论文没有给出任何示例)。
不允许将sqrt
的重载添加到std
命名空间。
但是,您可以使用完全限定名称,也可以通过添加using std::sqrt
赋予std::sqrt
首选项:
#include <cmath>
namespace X {
class Y { };
Y sqrt(Y) { return {}; }
double foo(double x) {
return std::sqrt(x);
}
} // namespace X
template <typename T>
T bar(T x){
using std::sqrt;
return sqrt(x);
}
double baz(double x){
using std::sqrt;
return sqrt(x);
}
double moo(double x){
return bar(x);
}
X::Y zoo(X::Y x){
return bar(x);
}
请注意, std::sqrt
禁用 ADL,而using std::sqrt
仍然允许 ADL 启动,例如从moo
和zoo
调用的bar
。
回答我自己的问题(但如果没有这里的讨论就不会找到它):
#include <cmath>
namespace X {
namespace details {
class Y { };
Y sqrt(Y);
} // ns details
using details::Y;
double foo(double x) { return sqrt(x); }
} // ns X
现在 foo 可以保持原样并且 sqrt(Y) 是可能的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.