ois*_*syn 25 c++ c++-concepts c++20 requires-expression
我想测试一个类型是否可以传递给某个函数,但我想在函数查找上使用 ADL 并包含来自某个命名空间的函数。
考虑这段代码:
#include <utility>
#include <vector>
template<class T>
concept Swappable = requires(T& a, T& b)
{
swap(a,b);
};
static_assert(Swappable<std::vector<int>>); // #1
static_assert(Swappable<int>); // #2
Run Code Online (Sandbox Code Playgroud)
#1 成功,它发现std::swap
becausestd
是 的关联命名空间std::vector<int>
。但 #2 失败了,内置类型没有关联的命名空间。
我该怎么写这样的东西:
template<class T>
concept Swappable = requires(T& a, T& b)
{
using std::swap; // illegal
swap(a,b);
};
Run Code Online (Sandbox Code Playgroud)
AFAIK,您不允许在 require 表达式中使用 using 声明。
(注意,虽然对此有一个完美的标准 C++ 概念,但std::swappable
此示例swap
仅用于说明。我并不是特别想测试某些东西是否实际上是可交换的,我只是想找到一种方法来实现这样的概念其中自定义函数在已知命名空间中具有默认实现,但可能在关联的命名空间中具有重载。)
编辑作为一种解决方法,我可以在一个单独的名称空间中实现这个概念,其中的名称被拉入。对此不太满意,但它有效。
namespace detail
{
using std::swap;
template<class T>
concept Swappable = requires(T& a, T& b)
{
swap(a,b);
};
}
// and then either use it
using detail::Swappable;
// or redefine it
template<class T>
concept Swappable = detail::Swappable<T>;
Run Code Online (Sandbox Code Playgroud)
Art*_*yer 23
您可以将其放入 lambda 中:
template<class T>
concept Swappable = []{
using std::swap;
return requires(T& a, T& b) { swap(a, b); };
}();
Run Code Online (Sandbox Code Playgroud)
避免使用旧using
的习语。相反,请使用自定义点等效项,例如ranges::swap
.
也就是说,您不应要求用户using
在其代码中使用基于 - 的习惯用法。提供一个可以执行所需操作的自定义点对象。可以限制重载operator()
/模板来创建习惯用法的效果,using
而不需要用户实际调用using
.
ranges::swap
这是如何完成此操作的一个很好的例子。
归档时间: |
|
查看次数: |
1420 次 |
最近记录: |