是否可以获取可变参数上的参数数量?

问题描述

我一直在研究如何使用可变数量的参数声明函数类成员,并且遇到了可变参数函数,但是我想知道是否有某种方法可以访问传递给函数的参数数量,,而不必像大多数文档所介绍的那样直接将其作为第一个参数传递。我也知道我可以使用可变参数模板或std::initializer_list,但是由于我希望传递多个相同类型的参数 ,所以这些参数看起来太通用和/或复杂语法。

#include <cstdarg>

bool func(int args...) {
    va_list list;
    va_start(list,args);   
    int val = args;
    while(val >=0) {
        std::cout << val << std::endl;
        val = va_arg(list,int);
    }
    return true;
}

bool other_func(int c,int args...) {
    va_list list;
    va_start(list,args);   
    int val = args;
    for (int i = 0; i<c; i++) {
        std::cout << val << std::endl;
        val = va_arg(list,int);
    }
    return true;
}

int main(int argc,char const *argv[]) {
    func(2,7,47,-1,23 /* ignored */);
    other_func(3 /* n of parameters */,2,47);

    return 0;
}

在这些特定示例中,func循环遍历输入自变量,直到找到负值(以说明问题并强制停止标志),而other_func要求将自变量数量设置为作为第一个参数传递。在我看来,这两种实现方式都存在缺陷和不安全之处,是否有更好的方法解决此问题?

解决方法

因为我一直想传递相同类型的多个参数

这正是std::initialiser_list<int>会给你的。

您似乎对可变参数功能有误。声明int args...并不意味着“一定数量的int参数”,而是意味着“一个名为args的int,后跟任意数量的任何类型的参数”

,

如果您使用C样式的varargs,则否,您一次只能解析一个参数列表。

如果您选择使用c ++ 11,则可以改用可变参数模板函数,并使用sizeof ...运算符获取参数包的大小。

template<typename ... Args>
void func(char * leading,Args const & ... args)
{
  /* sizeof...(Args) will give you the number of arguments */
} 
,

如果您有C ++ 17,可以在编译时使用可变参数非类型模板参数和折叠表达式来完成:(Live Demo

template<int... args>
constexpr bool func() {
    return ((args < 0) || ...);
}


int main() {
    static_assert(func<2,7,47,-1,23>());
    static_assert(!func<1,2,3>());

    return 0;
}

(如果您使用的是C ++ 20,则可以使用consteval而不是constexprDemo 2来执行编译时计算)


如果您坚持使用C ++ 11,那么仍然可以在编译时进行操作,但是我们将需要更多样板(Live Demo 3

#include <type_traits>

namespace detail
{
    template<bool...>
    struct disjunction;
    
    template<bool b>
    struct disjunction<b> : std::integral_constant<bool,b>
    {};
     
    template<bool left,bool... Bs>
    struct disjunction<left,Bs...> : std::conditional<left,disjunction<left>,disjunction<Bs...>>::type
    {};
}

template<int... args>
constexpr bool func() {
    static_assert(sizeof...(args) > 0,"Need to pass more than 1 integer");
    return detail::disjunction<(args < 0)...>::value;
}


int main() {
    static_assert(func<2,23>(),"There is one negative number");
    static_assert(!func<1,3>(),"There aren't any negative numbers");

    return 0;
}
,

否,没有标准的方法可以检测传递给(C风格)可变参数的参数的数量。您将必须在初始参数中传递数字,或使用某种可以被识别为序列结尾的终止符。为此,最好使用C ++工具。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...