如何制作C++包装器为std::vector越界提示添加文件行号并终止程序?
C++ std::vector越界检查包装器优化方案
问题解答
1. 是否可以不使用宏传递文件和行号?
在C中,__FILE__和__LINE__是预处理器宏,仅能在编译阶段展开。若需兼容C17及更早标准,必须依赖宏来传递调用点的文件和行号。但在C++20及之后,可使用标准库的std::source_location替代宏,它能自动捕获调用位置的信息,无需手动传递宏参数:
#include <vector> #include <cstdio> #include <stdexcept> #include <source_location> template<class T> typename T::value_type vec_get(const T& v, size_t idx, const std::source_location& loc = std::source_location::current()) { if (idx >= v.size()) { printf("%s:%d err std::vector %zu out of range size %zu\n", loc.file_name(), loc.line(), idx, v.size()); throw std::out_of_range("vec_get"); } return v.at(idx); }
调用时直接写vec_get(v, idx)即可,source_location会自动获取调用处的文件和行号。
2. 是否可以修改代码使其直接返回元素?
完全可以,只需将函数从void改为返回容器的元素类型,移除输出参数即可。以下是兼容C++11及以上标准的实现,同时保留宏传递文件行号:
#include <vector> #include <cstdio> #include <stdexcept> template<class T> typename T::value_type vec_get(const T& v, size_t idx, const char* file, int line) { if (idx >= v.size()) { printf("%s:%d err std::vector %zu out of range size %zu\n", file, line, idx, v.size()); throw std::out_of_range("vec_get"); } return v.at(idx); } #define VEC_GET(v, idx) vec_get(v, idx, __FILE__, __LINE__) int main() { std::vector<std::string> v; size_t idx = 0; // 直接返回赋值 std::string s = VEC_GET(v, idx); return 0; }
若使用C++14及以上标准,还可用auto简化返回类型声明:
template<class T> auto vec_get(const T& v, size_t idx, const char* file, int line) { if (idx >= v.size()) { printf("%s:%d err std::vector %zu out of range size %zu\n", file, line, idx, v.size()); throw std::out_of_range("vec_get"); } return v.at(idx); }
优化后程序输出
运行修改后的代码,输出效果与原代码一致,但调用方式更简洁:
$ ./vec_throw vec_throw.cpp:22 err std::vector 0 out of range size 0 terminate called after throwing an instance of 'std::out_of_range' what(): vec_get Aborted (core dumped)
内容的提问来源于stack exchange,提问作者rich
相关产品推荐
相关产品推荐

