我注意到,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;进行了特殊处理?形式或不适合取得论据,即它是否允许,但完全不切实际?
答案 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参数的函数的调用之前,编译器将始终选择其他重载。这对于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));
};