参数未知的可变参数函数

时间:2018-08-17 10:06:52

标签: c++

允许我说,我知道这个问题不适合大多数约定(如果有的话),但是出于对编程语言(C ++)的好奇和热爱,我还是会问这个问题。 随时用下面的答案或评论纠正我。

问题:

“我们可以在C ++中制作 variadic函数来接受多个参数(可能以前未知)的数据类型吗?实施?”

示例:

JavaScript示例

function buildArgs(... args) {
    let iterator = 0,
        length = args.length;

    for (iterator; iterator != length; iterator += 1) {
        let arg = args[iterator];
        build(arg)
    }
}

buildArgs(1); // Valid
buildArgs(1, "Hello"); // Valid
buildArgs(1, "Hello", null) // Valid

(假设的)C ++示例:

template <class... Args, typename data>
inline void buildArgs(Args... args) {
    int iterator = 0,
        length = sizeof args;

    for (iterator; iterator != length; iterator += 1) {
        data arg = args[iterator];
        build(arg);
    }
}

buildArgs(1); // Valid
buildArgs(1, "Hello"); // Valid
buildArgs(1, "Hello", NULL); // Valid

从给出的示例中,被认为对函数buildArgs有效的参数可以是任何数据类型(charintstd::string等),而函数buildArgs可以接受任意数量的有效参数。

我已经对C ++中的可变参数函数和模板进行了一些较小的研究,但我还没有找到答案。

再次,我不能说这个功能的实用性,但是我非常想知道是否有可能。

链接:

C中不同类型参数的变参函数variadic functions with different types of arguments in c

接受所有类型作为函数中的参数Accept all types as argument in function

C编程https://en.wikibooks.org/wiki/C_Programming/stdarg.h

C ++参考-参数包https://en.cppreference.com/w/cpp/language/parameter_pack

C ++参考-折叠表达式https://en.cppreference.com/w/cpp/language/fold

C中可变参数的数量Variable number of arguments in C++?

结论:

感谢您抽出宝贵的时间阅读我的问题,并感谢您的回答。

3 个答案:

答案 0 :(得分:2)

参数包是当前的C ++方式:

template<typename... Args> auto f(Args &&...args);

有了背包,你不能做很多,但仍然可以做些什么:

I。将它们存储在元组或(如果可能)数组或initialization_list s中:

auto t = std::tuple(std::forward<Args>(args)...);
CommonType a[] = {args...};
std::set<int> mySet{args...};

II。将它们用作函数参数(请参见上面的元组构造。)C ++中一个可识别包装的运算符是sizeof...

std::size_t currentArity = sizeof...(Args);

III。折叠包:

bool any = (args || ...);
(std::cout << ... << args);

set::set<int> myOtherSet;
(myOtherSet.insert(args), ...);

依此类推。

答案 1 :(得分:0)

对于C ++ 11,情况要复杂得多: Live example

template <typename T>
void printArgs(T &&x)
{
    std::cout << std::forward<T>(x) << " - ";
}

template <typename FirstT, typename ...Args>
void printArgs(FirstT &&first, Args&&...remaining)
{
    printArgs(std::forward<FirstT>(first));
    printArgs(std::forward<Args>(remaining)...);
}

如您所见,您没有参数迭代器。而是使用伪递归。
此外,还应考虑一种叫做“完美转发”的奇怪事物。

在这里您可以看到live example which gives debug information

问题是:

  

“我们可以用C ++制作可变参数函数来接受以下参数吗?   多种(可能以前未知)的数据类型以及如何处理   被实施?

答案为是。 C ++中的模板在使用时会实例化。因此,默认情况下,它们可以使用任何类型,直到遇到内部问题为止,例如某些功能不适用于特定类型。

在上面的示例中,您可以定义自定义类型,并且printArgs将失败,因为新类型没有operator<<(std::ostream &, const NewType &)。要解决该问题,您只需提供这样的运算符,printArgs就可以开始使用新类型了。

还有其他方法,例如CRTP (Curiously recurring template pattern)等。 C ++中的模板主题相当长且复杂。

答案 2 :(得分:0)

  

我们可以在C ++中制作可变参数函数来接受多种(可能以前未知)数据类型的参数吗?

是的。标头<cstdarg>中有库工具,可以简化此操作。

它们是:
 -va_start(启用对可变参数函数参数的访问),
 -va_arg(访问下一个可变参数函数参数),
 -va_copy(在C ++ 11中引入,它制作了可变参数函数参数的副本,
-va_end(结束对可变参数函数的遍历)和
-va_list(包含va_startva_argva_endva_copy所需的信息)。

另外,C,Go,C#,PHP,Java,JavaScript,Python,Perl 6支持此功能。