8 c++ argument-dependent-lookup c++-concepts c++20
例如,我想使用约束来确保isinf为模板参数实现该函数T。如果T是一float,double,long double或一体式,这可以通过以下方式进行:
#include <cmath>
template <typename T>
concept Test = requires (T a) {
std::isinf(a);
};
Run Code Online (Sandbox Code Playgroud)
但是,我也想将此约束用于我实现自己的isinf函数的自定义非标准数据类型。这个函数不包含在std命名空间中,所以我尝试了以下方法:
#include <cmath>
template <typename T>
concept Test = requires (T a) {
using std::isinf;
isinf(a);
};
Run Code Online (Sandbox Code Playgroud)
这是行不通的,因为 requires 子句中的每个语句都应该是有效的要求,而using std::isinf根本不是“要求”。
我看到了这个问题的两种解决方法:
将using std::isinf;子句移动到全局命名空间。但这引入isinf了我想避免的全局命名空间。
将using std::isinf;带有概念定义的子句封装在名为 的命名空间中ABC,然后using ABC::Test;直接添加到命名空间之后。这似乎有点奇怪。
有更好的解决方案吗?
此类事情在范围中的工作方式是通过创建自定义点对象。这与您的第二个选项非常相似(我们在自定义命名空间中粘贴了 using 声明),除了我们还提供了一种机制,让用户可以调用正确的方法,而isinf不必自己编写一堆相同类型的样板文件。
的自定义点对象isinf看起来像这样:
namespace N {
// make our own namespace
namespace impl {
// ... where we can bring in std::isinf
using std::isinf;
struct isinf_t {
// our type is constrained on unqualified isinf working
// in a context where std::isinf can be found
template <typename T>
requires requires (T t) {
{ isinf(t) } -> std::same_as<bool>;
}
constexpr bool operator()(T t) const {
// ... and just invokes that (we know it's valid and bool at this point)
return isinf(t);
}
};
}
// we provide an object such that `isinf(x)` incorporates ADL itself
inline constexpr auto isinf = impl::isinf_t{};
}
Run Code Online (Sandbox Code Playgroud)
现在我们有了一个对象,一个概念就直接出现了:
template <typename T>
concept Test = requires (T t) {
N::isinf(t);
}
Run Code Online (Sandbox Code Playgroud)
这正是这个概念的具体range定义方式。