为何带std::integral的auto&&运算符[]无法接受左值?
为什么带std::integral约束的auto&&万能引用只能接受右值?
按规则,auto&&应与模板中的T&&类似,代表万能引用而非右值引用,但某JSON库中json_t类的operator[]仅能接受右值,传入左值会触发错误:no operator "[]" matches these operands。相关代码如下:
#include <variant> struct json_t { using array_t = std::vector<json_t>; using object_t = std::map<std::string, json_t, std::less<>>; using null_t = std::nullptr_t; using val_t = std::variant<null_t, double, std::string, bool, array_t, object_t>; val_t data{}; json_t& operator[](std::integral auto&& index) { return std::get<array_t>(data)[index]; } }; int main() { int lvalue = 1; json_t f; f[1]; // WORKS f[lvalue]; // DOESN'T WORK f[std::move(lvalue)]; // DOES WORK }
传入右值或移除operator[]参数的std::integral约束后,调用均可正常执行,原因如下:
- 问题核心:
std::integral auto&&不是万能引用。万能引用的成立要求是无额外类型约束的auto&&,或是模板参数的T&&形式(依赖模板参数推导)。当给auto&&加上std::integral约束后,编译器会将其解析为绑定右值的引用,而非支持引用折叠的万能引用。 - 具体推导逻辑:
- 传入右值
1时,auto推导为int,std::integral<int>满足约束,参数类型为int&&,可以绑定右值,调用成功。 - 传入左值
lvalue时,auto仍推导为int,std::integral<int>虽满足约束,但int&&无法绑定左值,导致匹配失败。 - 传入
std::move(lvalue)时,实参转为右值,和第一种情况一致,调用成功。
- 传入右值
- 移除
std::integral约束后,auto&&恢复为万能引用:编译器会根据实参的左/右值属性,通过引用折叠生成对应的左值或右值引用,自然能接受左值。
内容的提问来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

