没有命名参数的变量函数

时间:2016-09-23 15:27:15

标签: c++ variadic-functions

我注意到,GCC和MSVC对以下代码感到满意:

readlink

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

我知道C在省略号之前至少需要一个命名的参数,它允许使用专门的#include <iostream> void foo(...); int main() { foo(); } void foo(...) { std::cout << "foo\n"; } va_start和{{1来处理任意数量的参数来自va_args(此处为va_end)标头的宏。否则,它甚至不会编译。

C ++是否对&#34;纯省略&#34;进行了特殊处理?形式或不适合取得论据,即它是否允许,但完全不切实际?

2 个答案:

答案 0 :(得分:4)

C++ Variadiac arguments are explained here。 C ++支持这种语法,但参数不可访问:

  

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

     

在C ++中,即使参数传递给此表单,也允许使用此表单   函数不可访问,通常用作后备   SFINAE中的过载,利用省略号的最低优先级   超载分辨率转换。可变参数的这种语法   在省略号之前没有逗号的1987 C ++中引入。什么时候   C89采用了C ++的函数原型,用它取代了语法   一个需要逗号。为了兼容性,C ++ 98同时接受这两者   C ++ - 样式f(int n...)和C样式f(int n, ...)

答案 1 :(得分:2)

在C ++中它是允许的,因为即使之前没有命名参数,...也只是一个无法访问的可变参数。

在C中,没有重载,并且具有仅接收...的函数可能是运行时错误的重要来源。无法接受的varargs是无用的C.

在C ++中,它目前用作sfinae的接收函数。在解析对具有variadic参数的函数的调用之前,编译器将始终选择其他重载。这对于s​​finae来说是实际的:

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));
};