带有可变数量参数的函数,没有任何显式参数 [英] Function with a variable number of parameters without any explicit parameters

查看:335
本文介绍了带有可变数量参数的函数,没有任何显式参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在C ++中使用以下形式的函数: void function(...){}



确实至少需要一个隐式参数吗?

解决方案

重复从一个评论:

看起来C99和C ++ 11在这里有一个有趣的区别:C ++ 11允许函数声明 void foo(...),因为 parameter-declaration-clause 中的 parameter-declaration-list 是可选的:[dcl.fct]



函数声明:


D1( parameter-declaration-clause cv-qualifier-seq opt ref-qualifier < sub> opt 异常规范 opt 属性说明符seq opt

参数:

lockquote

参数声明子句:

parameter-declaration-list opt ... opt

参数声明列表 ,...




< (请注意, parameter-declaration-list ... 在这里分别是 opt ,意思是你可以省去一个或另一个或两者,这个解释是由clang ++和g ++支持的。)



在C99中,这个声明是不允许的,因为参数-list 参数类型列表中不是可选的:6.7.5 / 1


$ b 函数声明:


直接声明符 parameter-type- list


参数:


参数类型列表:

parameter-list

参数列表 ,...


作为 va_start 等。宏/函数是从C99继承的,因此无法使用与省略号匹配的参数和空的 parameter-declaration-list 在C ++中。






C99中的 va_start 7.15.1.4


void va_start(va_list ap, parmN );

[...]

参数 parmN 是变量
参数列表中最右边参数的标识符(在,... 之前)。 [...]


重点是我的。 C99 假定在省略号之前有一个参数,因为在C99中声明一个带省略号但不带参数的函数是不合法的。






然而,我可以看到有两个理由使用带省略号的函数,但没有C ++中的任何参数:


  • 重载分辨率。将参数与省略号相匹配会导致重载排名非常低:省略号转换序列比任何用户定义的标准转换序列[over.ics.rank] / 2更差。这可以用于元编程:

      char foo(int); 
    int foo(...);

    struct S {};
    S s;
    sizeof(foo(42)); //产生1
    sizeof(foo(s)); //产生sizeof(int)


  • 实现定义的技巧。您的实现可能会提供一个平均值来访问与省略号匹配的参数。例如。请参阅 BobTFish 示例



How to work in C++ with functions the following form: void function(...) {}?

Do really need at least one implicit parameter?

解决方案

Repeating from a comment:

It seems there is an interesting difference between C99 and C++11 here: C++11 allows a function declaration void foo(...) because the parameter-declaration-list in the parameter-declaration-clause is optional: [dcl.fct]

Function declaration:

D1 ( parameter-declaration-clause ) cv-qualifier-seqopt ref-qualifieropt exception-specificationopt attribute-specifier-seqopt

Parameters:

parameter-declaration-clause:
parameter-declaration-listopt ...opt
parameter-declaration-list , ...

(Note how both the parameter-declaration-list and the ... are separately opt here, meaning you can leave out one or the other or both. This interpretation is supported by clang++ and g++.)

In C99, this declaration is not allowed since the parameter-list is not optional in the parameter-type-list: 6.7.5/1

Function declaration:

direct-declarator ( parameter-type-list )

Parameters:

parameter-type-list:
parameter-list
parameter-list , ...

As the va_start etc. macros/functions are inherited from C99, there's no way to use the arguments matched with the ellipsis with an empty parameter-declaration-list in C++.


Description of va_start in C99: 7.15.1.4

void va_start(va_list ap,parmN);
[...]
The parameter parmN is the identifier of the rightmost parameter in the variable parameter list in the function definition (the one just before the , ...). [...]

Emphasis mine. C99 assumes there's a parameter before the ellipsis, because it isn't legal in C99 to declare a function with an ellipsis but without parameters.


Yet, I can see two reasons to use a function with an ellipsis but w/o any parameters in C++:

  • Overload resolution. Matching arguments to an ellipsis leads to a very low ranking of the overload: An ellipsis conversion sequence is worse than any user-defined and standard conversion sequence [over.ics.rank]/2. This can be useful for metaprogramming:

    char foo(int);
    int  foo(...);
    
    struct S{};
    S s;
    sizeof(foo(42));    // yields 1
    sizeof(foo(s));     // yields sizeof(int)
    

  • Implementation-defined tricks. Your implementation may provide a mean to access those arguments matched with an ellipsis. E.g. see BobTFish's example

这篇关于带有可变数量参数的函数,没有任何显式参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆