如何向std::mismatch条件传递谓词以避免重复调用?
问题
调用多参数版本的std::mismatch时,需要根据条件二选一:要么使用标准默认比较逻辑,要么传入自定义谓词。要求:
- 避免重复书写
std::mismatch的完整调用代码 - 优先采用简洁的内联实现
- 高频执行的关键路径不能有额外的条件判断开销
- 禁止使用多态谓词,必须复用标准库的默认比较逻辑,不依赖编译器内联优化来保证性能
现有可运行的实现代码:
#include <algorithm> #include <iostream> #include <vector> struct some_functor { bool is_5_met = false; bool operator ()(auto lhs, auto rhs) { if (is_5_met) { return false; } if (lhs == 5 || rhs == 5) { is_5_met = true; } return lhs == rhs; } }; auto some_function(const std::vector<int>& data, long offset, bool cond) { return cond ? std::mismatch(data.begin(), data.end(), data.begin() + offset, data.end(), some_functor()).first - data.begin() : std::mismatch(data.begin(), data.end(), data.begin() + offset, data.end()).first - data.begin(); } int main() { std::vector<int> data = { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, }; std::cout << "Without 5 as sentinel : " << some_function(data, 7, false) << "\n"; std::cout << "With 5 as sentinel : " << some_function(data, 7, true) << "\n"; }
期望的简化写法(伪代码):
auto some_function(const std::vector<int>& data, long offset, bool cond) { return std::mismatch(data.begin(), data.end(), data.begin() + offset, data.end(), cond ? some_functor() : AND-DEFAULT-COMPARISON-HERE).first - data.begin(); }
解决方案
可以通过编译期分支或类型萃取的方式,在避免重复代码的同时保证关键路径无额外开销,以下是两种可行方案:
方案1:编译期分支封装(C++17+)
将std::mismatch的公共参数提取,用lambda封装编译期/运行期分支逻辑,避免重复书写完整调用:
#include <algorithm> #include <iostream> #include <vector> #include <type_traits> struct some_functor { bool is_5_met = false; bool operator ()(auto lhs, auto rhs) { if (is_5_met) { return false; } if (lhs == 5 || rhs == 5) { is_5_met = true; } return lhs == rhs; } }; auto some_function(const std::vector<int>& data, long offset, bool cond) { auto begin1 = data.begin(); auto end1 = data.end(); auto begin2 = data.begin() + offset; auto end2 = data.end(); auto result = [&]() { if (cond) { return std::mismatch(begin1, end1, begin2, end2, some_functor()); } else { return std::mismatch(begin1, end1, begin2, end2); } }(); return result.first - begin1; } int main() { std::vector<int> data = { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, }; std::cout << "Without 5 as sentinel : " << some_function(data, 7, false) << "\n"; std::cout << "With 5 as sentinel : " << some_function(data, 7, true) << "\n"; }
如果cond是编译期常量,编译器会直接消除无效分支;即使是运行时变量,也不会在谓词内部产生额外判断,完全复用原生std::mismatch的两种实现路径。
方案2:编译期谓词类型选择(C++11+,适合编译期已知条件)
利用std::conditional和标准库的std::equal_to<>(与std::mismatch默认比较逻辑完全一致),在编译期确定谓词类型:
#include <algorithm> #include <iostream> #include <vector> #include <functional> #include <type_traits> struct some_functor { bool is_5_met = false; bool operator ()(auto lhs, auto rhs) { if (is_5_met) { return false; } if (lhs == 5 || rhs == 5) { is_5_met = true; } return lhs == rhs; } }; // 编译期选择谓词类型 template<bool Cond> using PredType = std::conditional_t<Cond, some_functor, std::equal_to<>>; auto some_function(const std::vector<int>& data, long offset, bool cond) { // 若cond为编译期常量,直接实例化对应谓词 if constexpr (cond) { PredType<true> pred; auto result = std::mismatch(data.begin(), data.end(), data.begin() + offset, data.end(), pred); return result.first - data.begin(); } else { PredType<false> pred; auto result = std::mismatch(data.begin(), data.end(), data.begin() + offset, data.end(), pred); return result.first - data.begin(); } } int main() { std::vector<int> data = { 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, }; std::cout << "Without 5 as sentinel : " << some_function(data, 7, false) << "\n"; std::cout << "With 5 as sentinel : " << some_function(data, 7, true) << "\n"; }
此方案完全在编译期确定调用的std::mismatch版本,无任何运行时额外开销,且复用标准库默认比较逻辑,无需自行编写“平凡”谓词。
内容的提问来源于stack exchange,提问作者Damir Tenishev
相关产品推荐
相关产品推荐

