1

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

问题:

“我们能否在 C++ 中制作可变参数函数来接受多种(可能是以前未知的)数据类型的参数,以及如何实现它?”

例子:

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可以是任何数据类型(char、等) intstd::string而函数buildArgs可以接受任意数量的有效参数。

我已经对 C++ 中的可变参数函数和模板进行了一些小的研究,但我所看到的还没有回答这个问题。

同样,我不能说这个功能的实用性,但我很想看看它是否可能。

链接:

C 中具有不同类型参数的可变参数函数: c 中具有不同类型参数的可变参数函数

接受所有类型作为函数中的参数接受所有类型作为函数中的参数

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 中的可变参数数量:C++ 中可变数量的参数?

结论:

感谢您花时间阅读我的问题,更感谢您的回答。

4

3 回答 3

2

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

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

使用包,您可以做的不多,但仍然可以做一些事情:

I. 将它们存储在元组或(如果可能)数组或initialization_lists 中:

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

二、将它们用作函数参数(参见上面的元组构造。)C++ 中的一个包感知运算符是sizeof...

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

三、折叠包:

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

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

等等。

于 2018-08-17T10:33:01.163 回答
0

Can we make variadic functions in C++ that accept arguments of multiple (and possibly previously unknown) data types?

Yes. There are library facilities in the header <cstdarg> to make this easier.

They are:
- va_start (enables access to variadic function arguments),
- va_arg (accesses the next variadic function argument),
- va_copy (introduced in C++11 which makes a copy of the variadic function arguments,
- va_end (which ends traversal of the variadic function arguments) and
- va_list (which holds the information needed by va_start, va_arg, va_end, and va_copy).

Additionally C, Go, C#, PHP, Java, JavaScript, Python, Perl 6 support this feature.

于 2018-08-17T10:36:56.707 回答
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)...);
}

如您所见,您没有参数迭代器。而是使用伪递归。
还应该考虑一些奇怪的称为完美转发的东西。

在这里您可以看到提供调试信息的实时示例

问题是:

“我们能否在 C++ 中制作可变参数函数来接受多种(可能是以前未知的)数据类型的参数,以及如何实现它?

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

在上面的示例中,您可以定义自定义类型,并且printArgs由于没有operator<<(std::ostream &, const NewType &)新类型而将失败。要解决它,您必须简单地提供这样的运算符并printArgs开始为新类型工作。

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

于 2018-08-17T10:31:45.240 回答