C++如何获取operator[]调用方源码位置,有哪些可行替代方案?
解决方案
C++ 的 operator[] 作为成员函数重载时确实只能接收1个显式参数,无法直接加第二个默认参数存 std::source_location,可以用下面两种方案实现需求:
方案1:隐式参数包装(推荐,完全兼容原生[]语法)
利用隐式类型转换的构造函数默认参数在调用点求值的规则,把下标参数包装成自带源码位置的类型,operator[] 直接接收这个包装类型即可,调用方不需要修改任何[]写法:
#include <iostream> #include <source_location> // 下标包装类,支持int隐式转换,自动捕获调用点源码位置 struct IndexWithLoc { int idx; std::source_location loc; IndexWithLoc(int idx, std::source_location loc = std::source_location::current()) : idx(idx), loc(loc) {} }; struct Test { auto operator[](IndexWithLoc loc_with_idx) { // 直接取包装类里的loc,就是调用方的源码位置 return loc_with_idx.loc; } }; int main() { auto t = Test{}; auto s0 = t[5]; // 写法和原生[]完全一致 // 输出就是当前行的位置:main.cpp:24 int main() std::cout << s0.file_name() << ":" << s0.line() << ' ' << s0.function_name() << '\n'; return 0; }
方案2:宏包装(实现简单,需要修改调用写法)
宏是在调用点直接展开的,直接在宏里捕获源码位置传给类的自定义获取方法即可:
#include <iostream> #include <source_location> struct Test { auto get_with_loc(int idx, std::source_location loc = std::source_location::current()) { return loc; } }; // 定义宏包装调用 #define TEST_GET(t, idx) t.get_with_loc(idx) int main() { auto t = Test{}; auto s0 = TEST_GET(t, 5); std::cout << s0.file_name() << ":" << s0.line() << ' ' << s0.function_name() << '\n'; return 0; }
方案优缺点对比
- 隐式参数包装方案:优点是无调用方侵入,完全保留
[]的原生使用习惯;缺点如果operator[]原本支持多种下标类型,需要对应实现多个包装类,注意避免隐式转换二义性。 - 宏包装方案:优点是实现逻辑简单,不需要修改原有
operator[]的核心逻辑;缺点是需要调用方改用宏写法,不符合常规编码习惯,宏本身也有全局命名冲突、无法处理复杂表达式等问题。
内容的提问来源于stack exchange,提问作者user3520616
相关产品推荐
相关产品推荐

