gpt4 book ai didi

c++ - 防止参数包扩展中的数组衰减

转载 作者:可可西里 更新时间:2023-11-01 16:34:39 24 4
gpt4 key购买 nike

是否可以防止从参数包扩展的参数中的数组到指针衰减?

例如:

#include <iostream>

void foo() {
std::cout << "empty\n";
}

template <typename T, typename... Rest>
void foo(T &&t, Rest... rest) {
std::cout << "T, ...\n";
foo(rest...);
}

template <typename... Rest>
void foo(char *p, Rest... rest) {
std::cout << "char*, ...\n";
foo(rest...);
}

template <int N, typename... Rest>
void foo(char (&first)[N], Rest... rest) {
std::cout << "char[], ...\n";
foo(rest...);
}

int main() {
char a[2], b[2], c[2];
foo(a, b, c);
}

...输出:

char[], ...
char*, ...
char*, ...
empty

如您所见,第一次调用转到基于数组的重载,但后续调用转到基于指针的重载。 有什么方法可以让所有调用转到基于数组的重载吗?

相关:Problems specializing variable template function

最佳答案

您想通过右值引用传递参数包:

void foo(char (&first)[N], Rest&&... rest)
^^

所以整个代码看起来是这样的:

#include <iostream>

void foo() {
std::cout << "empty\n";
}

template <typename T, typename... Rest>
void foo(T &&t, Rest... rest) {
std::cout << "T, ...\n";
foo(rest...);
}

template <typename... Rest>
void foo(char *p, Rest... rest) {
std::cout << "char*, ...\n";
foo(rest...);
}

template <int N, typename... Rest>
void foo(char (&first)[N], Rest&&... rest) {
std::cout << "char[], ...\n";
foo(rest...);
}

int main() {
char a[2], b[2], c[2];
foo(a, b, c);
}

给出结果:

char[], ...
char[], ...
char[], ...
empty

我没有更改其他重载来执行相同的操作,但您通常希望它们也使用右值引用(如果它们确实被使用的话)。

编辑:至于为什么要这样做/为什么它有效:右值引用可以绑定(bind)到右值或左值。我们在这里关心的关键点是当它绑定(bind)到一个左值时,它仍然是一个左值。在数组的情况下,它保留其作为数组的身份,因此接收到的是一个数组。

当/如果我们按值传递数组时,它会经历正常的指针“衰减”,就像普通函数一样。

对于这种特定情况,我们也可以使用普通的左值引用——但如果我们这样做,那将适用于任何不是左值的类型。例如,如果我们试图调用 foo(1,2,3);,我们会得到一个错误,因为左值引用不能绑定(bind)到 123。为了解决这个问题,我们可以传递一个 const 左值引用,但是这样我们就不会将引用直接绑定(bind)到右值——我们会创建一个临时包含传递的右值的拷贝,然后将左值引用绑定(bind)到该临时拷贝。对于 int 的特定情况,这可能不是主要问题,但对于复制成本更高的东西(或者如果我们想要访问原始文件,而不是拷贝),这可能是个问题。

关于c++ - 防止参数包扩展中的数组衰减,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13922145/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com