在constexpr上下文中从std::views::split获取最后元素的更优方法?
问题:在constexpr上下文中,从std::views::split的结果中获取最后元素是否有更优方法?
鉴于split视图的接口有一定限制性,我想到了如下实现方案,但该方案需要遍历所有元素,并非理想选择。
#include <ranges> #include <iostream> #include <vector> #include <algorithm> constexpr std::string_view lastdot(std::string_view input) { std::string_view delim{"."}; std::string_view out; auto words = std::views::split(input, delim); std::size_t numwords = 0; std::ranges::for_each(words, [&](const auto word){ numwords++; }); std::size_t counter = 1; std::ranges::for_each(words, [&](auto word){ if(counter == numwords) out = std::string_view{word.begin(), word.end()}; counter++; }); return out; } int main() { constexpr auto out = lastdot("abc.def.ghi.jkl"); std::cout << out << '\n'; }
更优实现方案
你的当前实现需要两次遍历split视图,效率确实不高。这里提供两种更优方案:
方案一:直接定位最后一个分隔符(最优)
不需要借助std::views::split,直接在原字符串中找最后一个分隔符的位置,操作更直接高效,且完全支持constexpr:
#include <iostream> #include <string_view> constexpr std::string_view lastdot(std::string_view input) { const auto pos = input.find_last_of('.'); // 无分隔符则返回原字符串,否则返回分隔符后的部分 return pos == std::string_view::npos ? input : input.substr(pos + 1); } int main() { constexpr auto out1 = lastdot("abc.def.ghi.jkl"); constexpr auto out2 = lastdot("no_dot_here"); constexpr auto out3 = lastdot("trailing.dot."); std::cout << out1 << '\n'; // 输出 jkl std::cout << out2 << '\n'; // 输出 no_dot_here std::cout << out3 << '\n'; // 输出空字符串 }
方案优势
- 时间复杂度O(n):仅一次遍历原字符串,比原方案的两次遍历开销减半。
- 代码简洁直观:去掉冗余的split视图与两次循环,逻辑清晰。
- 完全兼容constexpr:
find_last_of和substr均支持constexpr上下文。
方案二:单次遍历split视图(基于split的优化)
如果必须依赖std::views::split,可以只遍历一次视图,实时更新最后一段的内容:
#include <ranges> #include <iostream> #include <string_view> constexpr std::string_view lastdot(std::string_view input) { std::string_view delim{"."}; std::string_view last_segment; for (auto segment : input | std::views::split(delim)) { last_segment = std::string_view(segment.begin(), segment.end()); } return last_segment; } int main() { constexpr auto out = lastdot("abc.def.ghi.jkl"); std::cout << out << '\n'; }
这个方案仅需一次遍历split视图,比原方案高效,但仍不如直接定位分隔符的方案——因为split本身需要遍历整个字符串完成分割,额外增加了开销。
内容的提问来源于stack exchange,提问作者1lumin
相关产品推荐
相关产品推荐

