繁体   English   中英

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

[英]Is it possible to get the number of arguments on a variadic function?

我一直在研究如何使用可变数量的参数声明函数或类成员,并遇到了可变参数函数,但是我想知道是否有某种方法可以访问传递给函数的参数数量,而不必通过正如大多数文档所介绍的那样,它直接作为第一个参数 我也知道我可以使用可变参数模板或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, 7, 47);

    return 0;
}

在这些特定示例中, func循环输入参数,直到找到负值(为了说明问题并强制停止标志),而other_func需要将参数数量作为第一个参数传递。 这两种实现在我看来都相当有缺陷和不安全,有没有更好的方法来解决这个问题?

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

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

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

如果您使用 C 风格的可变参数,则不能,您一次只能解析一个参数列表。

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

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

如果您有 C++17 可用,这一切都可以在编译时使用可变参数非类型模板参数和折叠表达式完成:(现场演示

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而不是constexpr强制编译时计算。演示 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, 7, 47, -1, 23>(), "There is one negative number");
    static_assert(!func<1, 2, 3>(), "There aren't any negative numbers");

    return 0;
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM