没有命名参数的可变函数

Variadic function without named argument

本文关键字:函数 参数      更新时间:2023-10-16

我注意到,GCC和MSVC都对下面的代码很满意:

#include <iostream>
void foo(...);
int main()
{
    foo();
}
void foo(...)
{
    std::cout << "foon";
}

更具体地说,代码在GCC 6.2.0和Visual Studio 2015下运行。

我知道C需要在省略号之前至少有一个命名的参数,这允许使用<stdarg.h>(这里是<cstdarg>)头中的专用va_start, va_argsva_end宏来处理任意数量的参数。否则,它甚至无法编译。

c++是否对"纯省略号"形式有一些特殊处理,或者它不适合获取参数,即它是允许的,但完全不切实际?

c++可变参数在这里解释。c++支持这种语法,但不能访问参数:

在C编程语言中,必须至少有一个命名参数出现在省略号参数之前,因此printz(...);无效。

在c++中,这种形式是允许的,即使传递给

的参数也是如此函数不可访问,通常用作回退在SFINAE中重载,利用省略号的最低优先级重载解析中的转换。可变参数的语法在1987年c++中引入,省略号前没有逗号。当C89采用c++中的函数原型,将语法替换为一个需要逗号。为了兼容性,c++ 98同时接受这两种方法c++风格的f(int n...)和C风格的f(int n, ...)

在c++中这是允许的,因为即使之前没有命名形参,...也只会是一个不可访问的可变参数。

在C语言中,没有重载,如果一个函数只接收...,可能会导致运行时错误。不可访问的变量在c中是没有用的。

在c++中,它目前用作sfinae的接收函数。如果可能,编译器总是在解析对带有可变参数的函数的调用之前选择其他重载。

template<typename F, typename... Ts>
struct is_callable {
private:
    template<typename T, typename... Args>
    static decltype(
        static_cast<void>(std::declval<T>()(std::declval<Args>()...)),
        std::true_type{}
    ) test(int);
    template<typename...>
    static std::false_type test(...); // not a template variadic, classic vararg here.
public:
    // Here, the compiler will try the first version of the function
    // Because '...' is not the preferred overload
    // If the return type expression don't yield to a type, the compiler
    // will have no choice but to pick the variadic one,
    // resulting in a std::false_type
    using type = decltype(test<F, Ts...>(0));
};