Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 指针与数组引用的数组索引序列扩展_C++_C++20_Libstdc++ - Fatal编程技术网

C++ 指针与数组引用的数组索引序列扩展

C++ 指针与数组引用的数组索引序列扩展,c++,c++20,libstdc++,C++,C++20,Libstdc++,我正在查看libstdc++中的to_array实现,注意到他们使用了一个巧妙的技巧,通过使用bool模板参数来决定函数是否应该将元素移动或复制到新创建的数组中,从而避免为函数编写额外的重载 我决定玩这个把戏,并编写了一些测试代码: template <typename ...P> void dummy(P...) {} template <typename T> int bar(T& ref) { printf("Copying %d\n&q

我正在查看libstdc++中的
to_array
实现,注意到他们使用了一个巧妙的技巧,通过使用
bool
模板参数来决定函数是否应该将元素移动或复制到新创建的数组中,从而避免为函数编写额外的重载

我决定玩这个把戏,并编写了一些测试代码:

template <typename ...P>
void dummy(P...) {}

template <typename T>
int bar(T& ref) {
    printf("Copying %d\n", ref);
    return ref;
}

template <typename T>
int bar(T&& ref) {
    printf("Moving %d\n", ref);
    T oldref = ref;
    ref = 0;
    return oldref;
}

template <bool Move, typename T, std::size_t... I>
void foo(T (&a)[sizeof...(I)], std::index_sequence<I...>) {
    if constexpr (Move) {
        dummy(bar(std::move(a[I]))...);
    } else {
        dummy(bar(a[I])...);
    }
}

template <typename T, std::size_t N>
void baz(T (&a)[N]) {
    foo<false>(a, std::make_index_sequence<N>{});
}

template <typename T, std::size_t N>
void baz(T (&&a)[N]) {
    foo<true>(a, std::make_index_sequence<N>{});
}
印刷品

Copying 4
Copying 3
Copying 2
Copying 1
1
2
3
4
Moving 4
Moving 3
Moving 2
Moving 1
0
0
0
0
在这两种情况下,都生成了相同的汇编代码,但是当使用
T(&a)[…]
时,函数调用如下所示

void foo(int(&)[4],std::integer\u序列)

其中as使用
T(a)[…]
导致函数调用看起来像

void foo(int*,std::integer\u序列)

区别在于第一个参数的签名从对int数组的引用变为指向int(也称为int数组)的指针

我用clang++11和g++11(没有优化)测试了代码,结果是一致的

我的问题是,当两个选项都生成相同的汇编代码并按预期执行时,为什么选择一个选项而不是另一个?是否存在这样的情况:它们的行为会有所不同,从而导致libstdc++使用
T(&a)
版本


是我的编译器资源管理器会话。

相比之下,有很多模板代码涵盖了一个非常简单的主题

在以下示例中,您通过引用传递数组:

事实上,我们可以对您更复杂的示例应用相同的测试:

void foo(T (&a)[sizeof...(I)], std::index_sequence<I...>) {
    for (const auto e : a) { (void)e; }  // Ok!
    // ...
}

void foo(T (a)[sizeof...(I)], std::index_sequence<I...>) {
    for (const auto e : a) { (void)e; }
        // Error: invalid range expression of type 'int *'; 
        // no viable 'begin' function available
    // ...
}
void foo(T(&a)[sizeof…(I)],std::index_序列){
for(const auto e:a){(void)e;}//好的!
// ...
}
void foo(T(a)[sizeof…(I)],std::index_序列){
对于(const auto e:a){(void)e;}
//错误:“int*”类型的范围表达式无效;
//没有可行的“开始”功能可用
// ...
}
#include <iostream>

void baz(int (&arr)[4]) {
    for (const auto e : arr) { std::cout << e << " "; }
}

int main() {
    int a1[] = {1, 2, 3, 4};
    baz(a1);  // 1 2 3 4
    
    return 0;
}
#include <iostream>

void baz(int arr[4]) {
    for (const auto e : arr) { std::cout << e << " "; }
}

int main() {
    int a1[] = {1, 2, 3, 4};
    baz(a1);  // error: cannot build range expression with array
              // function parameter 'arr' since parameter with array 
              // type 'int [4]' is treated as pointer type 'int *'
    
    return 0;
}
void foo(T (&a)[sizeof...(I)], std::index_sequence<I...>) {
    for (const auto e : a) { (void)e; }  // Ok!
    // ...
}

void foo(T (a)[sizeof...(I)], std::index_sequence<I...>) {
    for (const auto e : a) { (void)e; }
        // Error: invalid range expression of type 'int *'; 
        // no viable 'begin' function available
    // ...
}