当前位置: 首页 > 知识库问答 >
问题:

组合函数参数包和默认参数

邓德厚
2023-03-14

我有一个带有参数包的函数:

template<typename... Targs>
void tprintf(const char* format, Targs... args) {}

(实现应该不重要,签名才重要)。 我想使用gcc/clang内置函数添加source position作为默认参数。 类似于

template<typename... Targs>
void tprintf(const char* format, Targs... args,
             const char* file = __builtin_FILE(),
             unsigned line = __builtin_LINE()) {}

这将进行编译,但对它的调用并不像我所希望的那样将参数传递给args; 例如。

tprintf("%d%s", 0, "a");

gives(on Clang 10)

<source>:7:5: error: no matching function for call to 'tprintf'
    tprintf("%d%s", 0, "a");    
    ^~~~~~~
<source>:2:6: note: candidate function template not viable: no known conversion from 'const char [2]' to 'unsigned int' for 3rd argument
void tprintf(const char* format, Targs... args,    
     ^

这似乎表明args是空的,0文件“A”

实际上,在编写这个问题时,我发现显式地传递targs是有效的:

tprintf<int, char*>("%d%s", 0, "a");

这有可能避免吗?

共有2个答案

司徒炎彬
2023-03-14

解决方案是我们C++20的std::source_location:

#include <iostream>
#include <source_location>

template<typename... Targs, auto location = source_location::current()>
auto tprintf(char const* format, Targs const&... args) -> void {
    std::cout
        << std::format("{}:{}: ", location.file_name(), location.line())
        << std::format(format, args...);
}

auto main() -> int {
    tprintf("hello {}", "world"); // prints "example.cpp:12: hello world"
}

如果C++20不是一个选项(尤其是在目前这个时候,编译器不支持源位置),那么有一种方法可以在没有宏的情况下做到这一点。 您可以简单地对编译内置进行一点间接操作。

不能将默认参数放在变量参数之后,但可以将它们放在第一个参数的构造函数中,以具有相同的效果:

#include <cstdio>

struct location_and_format {
    constexpr location_and_format(
        char const* _format,
        char const* _file_name = __builtin_FILE(),
        unsigned _line = __builtin_LINE()
    ) noexcept : format{_format}, file_name{_file_name}, line{_line} {}

    char const* format;
    char const* file_name;
    unsigned line;
};

template<typename... Targs>
void tprintf(location_and_format format, Targs... args) {
    printf("%s:%u: ", format.file_name, format.line);
    printf(format.format, args...);
}

int main() {
    tprintf("hello %s", "world"); // prints example.cpp:22: hello world
}

活生生的例子

李招
2023-03-14

使用变量宏怎么样?

template<typename... Targs>
void tprintfhelper(const char* f, int l, const char* format, Targs... ) 
{
    std::cout << format << " " << l << " " << f << std::endl;
}

#define tprintf(...) tprintfhelper(__builtin_FILE(), __builtin_LINE() __VA_OPT__(,) ##__VA_ARGS__)

int main()
{
    tprintf("%d", 1, 2, 3, 4, 5, "dog");
}
 类似资料:
  • 对于一些函数,你可能希望它的一些参数是 可选 的,如果用户不想要为这些参数提供值的话,这些参数就使用默认值。这个功能借助于默认参数值完成。你可以在函数定义的形参名后加上赋值运算符(=)和默认值,从而给形参指定默认参数值。 注意,默认参数值应该是一个参数。更加准确的说,默认参数值应该是不可变的——这会在后面的章节中做详细解释。从现在开始,请记住这一点。 使用默认参数值 例7.5 使用默认参数值 #!

  • 在 C++中,定义函数时可以给形参指定一个默认的值,这样调用函数时如果没有给这个形参赋值(没有对应的实参),那么就使用这个默认的值。也就是说,调用函数时可以省略有默认值的参数。如果用户指定了参数的值,那么就使用用户指定的值,否则使用参数的默认值。 所谓默认参数,指的是当函数调用中省略了实参时自动使用的一个值,这个值就是给形参指定的默认值。下面是一个简单的示例: 运行结果: 10, 3.5, # 2

  • Scala 函数 Scala 可以为函数参数指定默认参数值,使用了默认参数,你在调用函数的过程中可以不需要传递参数,这时函数就会调用它的默认参数值,如果传递了参数,则传递值会取代默认值。实例如下: object Test { def main(args: Array[String]) { println( "返回值 : " + addInt() ); } def

  • 问题内容: 当我运行它时,它拒绝“ def a(…”,并用红色突出显示“(”。我不知道为什么。 问题答案: 让我在这里澄清两点: 首先,非默认参数不应跟随默认参数,这意味着您无法在函数中定义。在函数中定义参数的正确顺序为: 位置参数或非默认参数,即 关键字参数或默认参数,即 仅关键字参数,即 var-keyword参数,即 是位置参数 是可选参数 是关键字参数 是列表参数 仅限关键字 是var-k

  • 我们知道,在调用函数时如果不指定某个参数, Python 解释器会抛出异常。为了解决这个问题,Python 允许为参数设置默认值,即在定义函数时,直接给形式参数指定一个默认值。这样的话,即便调用函数时没有给拥有默认值的形参传递参数,该参数可以直接使用定义函数时设置的默认值。 Python 定义带有默认值参数的函数,其语法格式如下: def 函数名(...,形参名,形参名=默认值):     代码块

  • 本文向大家介绍Lua 默认参数,包括了Lua 默认参数的使用技巧和注意事项,需要的朋友参考一下 示例 该功能是一个简单的功能,并且效果很好。但是,如果我们刚刚打电话会发生什么sayHello()呢? 那不是很好。有两种解决方法: 您立即从函数返回: 您设置默认参数。 为此,只需使用此简单表达式 这个成语name = name or "Jack"之所以有效,是因为or在Lua中发生短路。如果左侧的项

  • 函数调用可能通常传递参数的特定值。程序员可以将该参数指定为默认参数,程序员可以提供这个参数的默认值。当函数调用中省略默认参数时,默认参数值自动传递给被调用函数。 默认参数必须是函数参数表中最右边(尾部)的参数。调用具有两个或多个默认参数的函数时,如果省略的参数不是参数表中最右边的参数,则该参数右边的所有参数也应省略。默认参数应在函数名第一次出现时指定,通常是在函数原型中。默认值可以是常量、全局变量

  • 问题内容: 我对PHP函数的默认值感到困惑。说我有一个这样的功能: 如果我想为$ x使用默认参数并为$ y设置不同的参数怎么办? 我一直在尝试不同的方法,但我变得更加困惑。例如,我尝试了以下两种方法: 但是这两个都不会为$ x产生适当的默认参数。我也试图通过变量名来设置它。 我完全希望这样的事情能奏效。但这根本不符合我的预期。似乎不管我做什么,每次调用该函数时,无论如何我都必须最终键入默认参数。而