首页 > 解决方案 > 模板参数推导与结构化绑定不同

问题描述

我正式被告知(一些书籍或网络),类型推导auto与参数类型推导相同template

但是,下面的代码无法成功编译,因为它会引发increment of read-only reference a错误。虽然模板版本扣除T为 typeint而不是const int &. 为什么这两种情况有不同的扣除结果?

#include "bits/stdc++.h"

using namespace std;

template <typename T>
T minmax2(T n1, T n2) {
    n1++;
    return n2;
}

int main() {
    auto [a, b] = minmax(1, 2); // minmax() return const T &
    a++;                        // compile error: can not alter read-only varaible.
    const int & c = 1, & d = 2;
    minmax2(c, d);              // the same parameter type, don't raise error
}

另一个例子:

int tmp = 1;
const int & test() {
    return tmp;
}

template <typename T>
void test1(T n) {
    n++;  // no error
}
int main() {
    auto a = test(); // If the satement is true, I expect this is the same as test1.
    a++; // no compile error, which is different with the previous code exp
    const int & b = 2;
    test1(b);
}

标签: c++genericsstl

解决方案


我认为您的困惑来自这样一个事实,即结构化绑定的行为与普通绑定有点不同auto,至少从用户的角度来看是这样。先考虑后者:

const int& i = 0;
auto j = i;
std::cout << &i << std::endl;
std::cout << &j << std::endl; // different address
j++; // compiles

在这里,iandj指的是不同的对象和类型jint(不是const intconst int&)。这与按值传递参数时的模板参数推导完全对应。

但是对于结构化绑定,情况就不同了:

int c = 0, d = 0;
auto [a, b] = std::pair<const int&, const int&>(c, d);
std::cout << &a << std::endl;
std::cout << &c << std::endl; // same address
// a++; // would not compile

在这里,and 的类型abconst int&两者都ac的是同一个对象。

现场演示:https ://godbolt.org/z/Wq1zsz


实际上,结构化绑定也忽略了初始化表达式的const引用部分,但在“外部”级别,即std::pair在我们的例子中:

const auto& p = std::make_pair(c, d);
auto [x, y] = p;
std::cout << &p.first << std::endl;
std::cout << &x << std::endl; // different address

这里,x是一个类型为 的新对象int。如果我们const auto& [x, y] = p;改为使用 then ,则x引用p.first其类型为const int&.


推荐阅读