【问题标题】:Variable length argument list of set type集合类型的变长参数列表
【发布时间】:2012-10-07 18:24:55
【问题描述】:

好吧,我很确定之前已经以某种方式讨论过这个问题,但我显然太愚蠢了,找不到它。

首先:我不是在寻找 va_list 和其他宏。 我正在寻找的是类似于 main-function 参数的东西。

你们都知道的默认原型是:

int main(int argc, char *argv[]);

现在,我想为我的程序提供类似的东西,但不知道具体如何。

假设我们有这个函数:

void Function(int argc, unsigned short *args[]) {
    for(int i = 0; i < argc; ++i) printf("%hu ", args[i]);
}

我想要这样的函数调用:

Function(5, 1, 2, 3, 4, 5);

这行得通吗? 因为我不想要 va_list 的“杂乱无章”,也不想创建:

void AnotherFunction() {
    unsigned short Args[] = { 1, 2, 3, 4, 5 };
    Function(5, Args);
}

只是因为在这种情况下我只需要一个简单的指针。 有人可以指出我正确的方向吗?非常感谢。

编辑: 谢谢大家的宝贵意见。我将满足于“目前不适用于标准 C/C++,并寻找一种不同的方法来解决我的问题。

再次感谢您。

【问题讨论】:

  • @chris 不,恐怕我只能使用标准 C++。
  • 啊,这个想法就完蛋了。无论如何都应该采用向量。
  • @ATaylor 看起来你一直在用 Java 编程。据我所知,C++ 没有这个“特性”,这是 Java 实现可变参数的结果。
  • 你想要什么? C 和 C++ 在这方面完全不同
  • @Code-Guru 我也一直在用 Java 编程,这是真的。我只是......你知道,希望在 C 或 C++ 中它是可能的。

标签: c++ c function arguments


【解决方案1】:

一个g++具体的解决方案:

const size_t MAX_ARGS = 42;

void Function(int argc, const unsigned short (&args)[MAX_ARGS])
{
}

int main()
{
    Function(5, {1,2,3,4,5});
}

如果你实际上不需要argc参数,你可以写一个模板:

template<size_t N>
void Function(const unsigned short(&args)[N])
{
    // use N
}

这适用于 C++03。数组必须是 const,否则你不能像这样传递一个临时初始化列表。如果需要修改函数内部的元素,则需要进行复制。

【讨论】:

  • @Vaughn 我不知道,谢谢。 (我也从未使用过,我只是尝试过一次看看是否有效,从不费心检查它是否合法)。
  • 你得到了“正确”,因为基本上你是唯一一个解决方案“可能在特定情况下有效”的人,但不是一场噩梦。
  • @ATaylor 你真的看过另一个答案吗?我的解决方案有效且可移植。这应该符合您“在特定情况下可能有效”的标准。
  • @KonradRudolph 是的,我确实看过它们。但是,我没有 C++11 编译器可供使用,这让您的建议变得不可能。是的,它在特定情况下确实有效,但我无法满足。
【解决方案2】:

由于您还使用 C: 标记,因此在 C 中您可以使用宏与所谓的复合文字组合

#define  FUNCTION(ARGC, ...) (Function((ARGC), (unsigned short[]){ __VA_ARGS__ }))

这比古老的va_list 函数更安全,因为它将列表中的所有表达式转换为unsigned short

现代 C++ 现在还具有用于宏预处理阶段的 VA_ARGS 功能。但我不知道您将如何创建一个临时向量,并使用这些值进行初始化。

【讨论】:

    【解决方案3】:

    使用默认参数。

    Function(int argc, unsigned short *args[], int a = 2, int b = 3, int c = 4) ;
    

    或您想要的任何类型。默认值,如本例中的最后三个,不需要传递给函数。你可以这样调用函数..

    Function (argc, args, 5, 4, 3) ;  //have to remember the maximum no. of parameters
    

    我不知道你为什么要在你的程序中做这种事情。如果您不需要额外的变量,为什么要将它们包含在您的程序中? 但是

    【讨论】:

    • 使用默认参数,您仍然需要提前知道所需的最大参数数量。 (此评论更多是针对 OP 或未来的访问者,而不是回答者。)
    • 是的,Code-Guru 是正确的。我不知道我将使用多少个参数。这是一个类树,你明白吗?
    • 那样的话,恐怕我觉得没有办法了。
    【解决方案4】:

    要在 C 中编写类似的函数,您需要 va_list 和其他宏。这源于从 C 到汇编的转换。在汇编中,您可以在堆栈框架上“查找”以查看可能传递给函数的更多参数。

    但是,在 C 中,必须使用 va_list 类型和宏来完成此操作,因为没有其他内置机制可以使用,同时仍保持函数的原型(参数的数量和类型)。

    请参阅http://www.gnu.org/software/libc/manual/html_node/Variadic-Functions.html

    【讨论】:

      【解决方案5】:

      这里有两个标准的 C++ 解决方案。两者都需要支持 C++11 的编译器:

      #include <iostream>
      #include <algorithm>
      #include <vector>
      #include <iterator>
      #include <utility>
      
      template <typename T, typename... Us>
      struct first_of_helper {
          typedef T type;
      };
      
      template <typename... Ts>
      using FirstOf = typename first_of_helper<Ts...>::type;
      
      template <typename... Ts>
      void f(Ts&&... args) {
          typedef FirstOf<Ts...> T;
          std::vector<T> v_args{std::forward<Ts>(args)...};
          std::copy(v_args.begin(), v_args.end(), std::ostream_iterator<T>(std::cout, " "));
          std::cout << "\n";
      }
      
      template <typename T>
      void g(std::initializer_list<T> args) {
          std::copy(args.begin(), args.end(), std::ostream_iterator<T>(std::cout, " "));
          std::cout << "\n";
      }
      
      int main() {
          f(1, 2, 3, 4);
          g({1, 2, 3, 4});
      }
      

      在 C++11 之前,唯一可移植的解决方案是通过 va_args。考虑一下:如果不需要 va_args 因为您可以编写更简单的代码,那么它为什么会存在呢?

      【讨论】:

        【解决方案6】:

        在 C++ 中基本上有两种方法可以做变量参数:

        1. 继承自 C 的可变参数语法,使用 va_list 等。

        2. 创建容器以传入参数。这个容器可以是数组、std::vector、std::list等。

        您提出的通过直接传递参数并允许编译器构造容器的解决方案非常具有 Java 风格。这就是 Sun/Oracle 决定在 Java 5 中实现 var-args 的方式,结果证明这是一个非常方便的特性。不幸的是,C++ 不支持这种语法 afaik。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-17
          • 1970-01-01
          • 2011-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多