создание std::source_location с пользовательскими значениями
Я интегрирую стороннюю библиотеку в свой проект. Библиотека предоставляет перехватчики для перенаправления сообщений журнала и предоставляет структуру с файлом, строкой, серьезностью, сообщением и т. д. Мой проект использует
3 ответа
Обычно это невозможно; единственные стандартизированные способы получения a — это его конструктор по умолчанию (который дает вам пустой объект) и (который дает вам объект со значениями, соответствующими месту вызова). Стандартизированных установщиков не существует, поэтому вы не можете портативно изменять значения полей существующего файла .
Если мы рассмотрим основные реализации: MS-STL, libstdc++, libc++; вы можете видеть, что, несмотря на то, что аргументы для них могут быть разными в каждом случае (поэтому код будет непереносимым, даже ориентированным только на эти три реализации, несмотря на то, что интерфейс может быть изменен в любое время, поскольку это не предназначен для вызова пользовательским кодом), а в случае libstdc++ передаваемый тип является закрытым. Кроме того, тип не имеет семантики владения, поэтому вам необходимо обеспечить время жизни, чтобы избежать висячих указателей. Окончательно,current()
являетсяconsteval
поэтому вы в любом случае не сможете вызвать его со значениями времени выполнения.
Остается только изменить личные данныеsource_location
пример; хотя это и возможно с помощью обычных приемов, это все равно будет иметь проблемы со временем жизни, будет хрупким и будет иметь неопределенное поведение, поскольку изменение объектов стандартной библиотеки не разрешено.
Было бы лучше переключить вашу библиотеку на использование исходного класса местоположения, предназначенного для конструирования со значениями времени выполнения. Например, вы можете использоватьboost::source_location
или напишите свой собственный.
Как мне построить std::source_location из значений, предоставленных библиотекой?
Вы не знаете.
std::source_location
специально разработан для того, чтобы гарантировать, что любой конкретный экземпляр получил свои данные от компилятора , а не «значения, предоставленные библиотекой». Для этого необходимо, чтобы объект был создан внутри исходного кода библиотеки. Если это не было написано для этого, то вы не можете получить за это.
Вам необходимо создать перегрузку вашей функции журналирования, которая может принимать значения напрямую, а не использоватьsource_location
.
namespace notstd {
struct source_state {
std::uint_least_t line = 0;
std::uint_least_t column = 0;
std::string file;
std::string function;
};
struct source_location : std::source_location {
std::optional<source_state> ss;
constexpr source_location(std::source_location const& base):
std::source_location(base)
{}
source_location(source_state manual):
ss(std::move(manual))
{}
constexpr std::uint_least_t line() const {
if (ss) return ss->line;
return std::source_location::line();
}
constexpr std::uint_least_t column() const {
if (ss) return ss->column;
return std::source_location::column();
}
char const* file_name() const {
if (ss) return ss->file.c_str();
return std::source_location::file_name();
}
char const* function_name() const {
if (ss) return ss->function.c_str();
return std::source_location::function_name();
}
};
}
это довольно близкая к полной замене замена, позволяющая вручную указывать параметры.
Просто замените свое собственное использованиеstd::source_location
с вышеизложенным. Ваш существующий код, вероятно, скомпилируется. (самая большая разница в API заключается в том, что имя файла/имя функции больше не являются constexpr; это сложно реализовать, поэтому я этого не сделал)
И теперь вы можете использоватьnotstd::source_state
для перехода в ручное местоположение.