繁体   English   中英

在命名空间 std 中重载 function 模板

[英]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 启动,例如从moozoo调用的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM