能否在requires表达式中使用using声明实现含ADL的函数查找?
如何在Concept中结合ADL与特定命名空间的函数查找
我想要测试某类型是否能传入目标函数,同时在函数查找过程中启用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 断言失败
这段代码的问题是:
#1断言成功,因为std是std::vector<int>的关联命名空间,通过ADL能找到std::swap;但#2断言失败,因为内置类型int没有关联命名空间,全局域也找不到swap函数。
我原本想通过在requires表达式里引入std::swap来解决这个问题,但requires表达式内不允许使用using声明,下面的写法是非法的:
template<class T> concept Swappable = requires(T& a, T& b) { using std::swap; // 非法:requires表达式内不能使用using声明 swap(a,b); };
注:尽管C++标准库已经有完善的
std::swappable概念,这里只是用swap做演示。我的真实需求不是测试类型是否可交换,而是要实现一种自定义Concept:目标函数在某个已知命名空间有默认实现,但类型的关联命名空间可能存在更合适的重载版本,需要同时支持ADL查找和默认命名空间的函数匹配。
我目前找到一个临时可行的方案——在单独的细节命名空间里先引入目标函数,再在这个命名空间内定义Concept:
namespace detail { using std::swap; template<class T> concept Swappable = requires(T& a, T& b) { swap(a,b); }; } // 使用方式1:直接引入使用 using detail::Swappable; // 使用方式2:重新对外暴露Concept template<class T> concept Swappable = detail::Swappable<T>;
这个方案能正常工作,但不算完美。
内容的提问来源于stack exchange,提问作者oisyn
相关产品推荐
相关产品推荐

