如何使用boost::hana检测方法存在性实现通用容器contains函数
通用容器contains模板函数实现
实现逻辑要求
- 优先调用容器原生的
.find(value)方法(适配std::set、std::map、std::unordered_set等做过专属查找优化的容器) - 容器不存在原生find方法时,回退调用
std::find(xs.cbegin(), xs.cend(), v)实现遍历查找
原有代码问题
你使用boost::hana::is_valid生成的是检测谓词函数,不是直接的布尔结果,需要传入目标容器和查找值调用该谓词,才能得到编译期的成员方法存在性判断结果。
修正后可运行版本(基于Boost.Hana)
#include <boost/hana/is_valid.hpp> #include <algorithm> #include <iterator> template<typename TContainer, typename T> bool contains(const TContainer& container, const T& v) { // 定义检测逻辑:判断容器是否存在接收v作为参数的find方法 constexpr auto has_valid_find = boost::hana::is_valid( [](auto&& xs, auto&& x) -> decltype(xs.find(x)) {} ); if constexpr (has_valid_find(container, v)) { return container.find(v) != container.cend(); } else { return std::find(container.cbegin(), container.cend(), v) != container.cend(); } }
无Boost依赖版本(纯C++17 SFINAE实现)
如果你的项目没有引入Boost依赖,可以用原生C++语法实现相同逻辑:
#include <algorithm> #include <iterator> #include <type_traits> template<typename TContainer, typename T> bool contains(const TContainer& container, const T& v) { if constexpr (std::is_invocable_v< decltype([](const TContainer& c, const T& val) { return c.find(val); }), const TContainer&, const T& >) { return container.find(v) != container.cend(); } else { return std::find(container.cbegin(), container.cend(), v) != container.cend(); } }
使用示例
#include <vector> #include <set> #include <iostream> int main() { std::vector<int> test_vec = {1, 3, 5, 7}; std::set<int> test_set = {2, 4, 6, 8}; std::cout << std::boolalpha; // vector无find方法,走std::find分支,输出true std::cout << contains(test_vec, 5) << "\n"; // set有原生find方法,走优化分支,输出false std::cout << contains(test_set, 5) << "\n"; return 0; }
内容的提问来源于stack exchange,提问作者TesX
相关产品推荐
相关产品推荐

