将std::vector设为模板函数局部变量后编译异常,哪个编译器处理正确?
问题描述
我编写了如下代码:
#include <iostream> #include <span> #include <vector> std::vector v{1,2,3,4,5,6}; template <template <typename, std::size_t> class S> S<int, std::dynamic_extent> GetSpan() { return v; } int main() { auto x = GetSpan<std::span>(); return 0; }
这段代码可被GCC和Clang正常编译。但当我将std::vector改为GetSpan()函数的局部变量,即:
template <template <typename, std::size_t> class S> S<int, std::dynamic_extent> GetSpan() { std::vector v{1,2,3,4,5,6}; return v; }
此时Clang仍可正常编译,但GCC会拒绝编译。请问哪个编译器的处理符合C++标准?原因是什么?
答案
GCC的处理符合C++标准,具体原因如下:
- 当
std::vector是GetSpan()的局部变量时,return v;语句中的v是自动存储期对象,在返回时会被视为亡值(xvalue),属于右值范畴。 std::span提供的容器构造函数(template<class Container> constexpr span(Container& cont);)要求参数是非const左值引用,而C++标准明确规定右值(包括亡值)无法绑定到非const左值引用。- 因此,用局部
vector(亡值)隐式构造std::span的操作违反了标准规则,GCC拒绝编译是正确的。 - Clang允许编译属于非标准行为,它错误地将return语句中的局部变量当作左值处理,绕过了右值无法绑定非const左值引用的限制。
内容的提问来源于stack exchange,提问作者Karen Baghdasaryan
相关产品推荐
相关产品推荐

