如何用Boost Hana懒执行lambda列表中首个未被SFINAE排除的函数
问题原因
你遇到的插入重复值问题,本质是hana::transform会遍历tuple所有元素并立即执行传入的转换函数,即使后续find_if只会用到第一个匹配的结果,所有lambda都被触发执行导致重复插入。而你尝试的懒求值版本编译失败,是因为hana::is_just不能直接作用于未求值的lazy包装对象,需要先对惰性值求值再做判断。
解决方案
最优实现:使用hana::monadic_fold_left
利用hana::optional的单子短路特性,monadic_fold_left在遍历过程中只要某次调用返回hana::just就会立即终止遍历,后续操作不会被执行,完美匹配你需要适配任意数量lambda的需求:
#include <boost/hana.hpp> #include <vector> #include <iostream> namespace hana = boost::hana; template <class T> void addToContainer(T &container, const typename T::value_type &element) { auto insert_op = hana::sfinae([&](auto& c) { return c.insert(end(c), element); }); auto push_back_op = hana::sfinae([&](auto& c) { c.push_back(element); return --end(c); }); // 可任意扩展操作列表,无需修改逻辑适配更多lambda auto ops = hana::make_tuple(insert_op, push_back_op); // 短路执行:碰到第一个返回just的操作就停止遍历 hana::monadic_fold_left<hana::optional>(ops, hana::nothing, [&](auto, auto op) { return op(container); }); } // 测试用例 void test() { std::vector<int> v{1, 2}; std::vector<int> expected{1, 2, 3}; addToContainer(v, 3); if (v != expected) { std::cout << "Implementation failed: Expected v to have " << expected.size() << " elements, but it has " << v.size() << std::endl; } else { std::cout << "Implementation succeeded." << std::endl; } } int main() { test(); return 0; }
基于find_if的实现
如果一定要用find_if实现,可以将执行逻辑放到谓词中,利用find_if的短路特性仅执行到第一个匹配的操作即可:
template <class T> void addToContainer(T &container, const typename T::value_type &element) { auto insert_op = hana::sfinae([&](auto& c) { return c.insert(end(c), element); }); auto push_back_op = hana::sfinae([&](auto& c) { c.push_back(element); return --end(c); }); auto ops = hana::make_tuple(insert_op, push_back_op); hana::find_if(ops, [&](auto op) { auto res = op(container); return hana::is_just(res); }); }
hana::find_if默认是短路遍历,只要谓词返回true就会立即停止,后续的lambda不会被触发执行,不会出现重复插入问题。
内容的提问来源于stack exchange,提问作者Jan15
相关产品推荐
相关产品推荐

