L. *_* F. 33 c++ default-arguments variadic-templates c++20 std-source-location
C ++ 20功能std::source_location
用于捕获有关调用函数的上下文的信息。当我尝试将其与可变参数模板函数一起使用时,遇到一个问题:我看不到放置source_location
参数的地方。
以下操作无效,因为可变参数必须在末尾:
// doesn't work
template <typename... Args>
void debug(Args&&... args,
const std::source_location& loc = std::source_location::current());
Run Code Online (Sandbox Code Playgroud)
以下内容也不起作用,因为调用者将被介于两者之间的参数所困扰:
// doesn't work either, because ...
template <typename... Args>
void debug(const std::source_location& loc = std::source_location::current(),
Args&&... args);
// the caller will get confused
debug(42); // error: cannot convert 42 to std::source_location
Run Code Online (Sandbox Code Playgroud)
可以在可变参数模板中无缝使用的评论中告诉我std::source_location
,但是我很难弄清楚该如何做。如何std::source_location
与可变参数模板函数一起使用?
Pio*_*cki 30
template <typename... Ts>
struct debug
{
debug(Ts&&... ts, const std::source_location& loc = std::source_location::current());
};
template <typename... Ts>
debug(Ts&&...) -> debug<Ts...>;
Run Code Online (Sandbox Code Playgroud)
测试:
int main()
{
debug(5, 'A', 3.14f, "foo");
}
Run Code Online (Sandbox Code Playgroud)
只需将您的参数放在一个元组中,就不需要宏。
#include <source_location>
#include <tuple>
template <typename... Args>
void debug(
std::tuple<Args...> args,
const std::source_location& loc = std::source_location::current())
{
std::cout
<< "debug() called from source location "
<< loc.file_name() << ":" << loc.line() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
这有效*。
从技术上讲,您可以编写:
template <typename T>
void debug(
T arg,
const std::source_location& loc = std::source_location::current())
{
std::cout
<< "debug() called from source location "
<< loc.file_name() << ":" << loc.line() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
但是然后您可能不得不跳过一些障碍才能获得参数类型。
*在链接到的示例中,我正在使用,<experimental/source_location>
因为这是编译器现在接受的。另外,我添加了一些代码来打印参数元组。
小智 7
如果您的函数在可变参数之前有一个固定参数,例如 printf 格式字符串,您可以将该参数包装在一个结构中,该结构在其构造函数中捕获 source_location:
struct FormatWithLocation {
const char* value;
std::source_location loc;
FormatWithLocation(const char* s,
const std::source_location& l = std::source_location::current())
: value(s), loc(l) {}
};
template <typename... Args>
void debug(FormatWithLocation fmt, Args&&... args) {
printf("%s:%d] ", fmt.loc.file_name(), fmt.loc.line());
printf(fmt.value, args...);
}
int main() { debug("hello %s\n", "world"); }
Run Code Online (Sandbox Code Playgroud)
template <typename... Args>
void debug(Args&&... args,
const std::source_location& loc = std::source_location::current());
Run Code Online (Sandbox Code Playgroud)
“有效”,但需要指定模板参数,因为存在不可推导的参数,因为没有最后一个:
debug<int>(42);
Run Code Online (Sandbox Code Playgroud)
可能的(不完美的)替代方案包括:
使用具有硬编码限制的重载(“处理”可变参数的旧可能方法):
// 0 arguments
void debug(const std::source_location& loc = std::source_location::current());
// 1 argument
template <typename T0>
void debug(T0&& t0,
const std::source_location& loc = std::source_location::current());
// 2 arguments
template <typename T0, typename T1>
void debug(T0&& t0, T1&& t1,
const std::source_location& loc = std::source_location::current());
// ...
Run Code Online (Sandbox Code Playgroud)
放在source_location
第一个位置,没有默认值:
template <typename... Args>
void debug(const std::source_location& loc, Args&&... args);
Run Code Online (Sandbox Code Playgroud)
和
debug(std::source_location::current(), 42);
Run Code Online (Sandbox Code Playgroud)
与重载类似,但仅使用元组作为组
template <typename Tuple>
void debug(Tuple&& t,
const std::source_location& loc = std::source_location::current());
Run Code Online (Sandbox Code Playgroud)
或者
template <typename ... Ts>
void debug(const std::tuple<Ts...>& t,
const std::source_location& loc = std::source_location::current());
Run Code Online (Sandbox Code Playgroud)
随着使用
debug(std::make_tuple(42));
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
937 次 |
最近记录: |