问题
I would like to write a function that accesses the file and line number of the location in which it gets called.
It would look like this:
fn main() {
prints_calling_location(); // would print `called from line: 2`
prints_calling_location(); // would print `called from line: 3`
}
fn prints_calling_location() {
let caller_line_number = /* ??? */;
println!("called from line: {}", caller_line_number);
}
回答1:
RFC 2091: Implicit caller location adds the track_caller
feature which enables a function to access the location of its caller.
Short answer: to obtain the location in which your function gets called, mark it with #[track_caller]
and use std::panic::Location::caller in its body.
Following from that answer, your example would look like this:
#![feature(track_caller)]
fn main() {
prints_calling_location(); // would print `called from line: 2`
prints_calling_location(); // would print `called from line: 3`
}
#[track_caller]
fn prints_calling_location() {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();
println!("called from line: {}", caller_line_number);
}
playground link
More specifically, the function std::panic::Location::caller has two behaviors:
- Within a function marked
#[track_caller]
, it returns a&'static Location<'static>
which you can use to find out the file, line number, and column number in which your function gets called. Within a function that doesn't have
#[track_caller]
, it has the error-prone behavior of returning the actual location where you've invoked it, not where your function gets called, for example:#![feature(track_caller)] fn main() { oops(); // ^ prints `line: 10` instead of the expected `line: 4` } // note: missing #[track_caller] here fn oops() { println!("line: {}", std::panic::Location::caller().line()); }
playground link
回答2:
An alternative to using the "Implicit caller location" (which may not be available/suitable to you for whatever reason) is to do things the C way. I.e. hide your function behind a macro.
macro_rules! prints_calling_location {
() => {
let caller_line_number = line!();
println!("called from line: {}", caller_line_number);
};
}
fn main() {
prints_calling_location!(); // prints `called from line: 10`
prints_calling_location!(); // prints `called from line: 11`
}
playground link
来源:https://stackoverflow.com/questions/60714284/how-can-i-access-a-functions-calling-location-each-time-its-called