c++ - 在模板化函数中将 std::vector 设置为本地会导致编译失败

标签 c++ templates c++17 language-lawyer

我正在使用以下代码。

#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;
}

这是accepted由 GCC 和 Clang 共同编写。但是,如果我在函数 GetSpan() 中将 std::vector 设为本地,i。

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;
}

叮当依然accepts代码,但 gcc 拒绝它。 哪个编译器在这里,为什么?

最佳答案

您的代码无法在 C++23 模式下编译。这是因为返回变量时进行了简化的隐式移动。 (参见:cpppreferenceP2266R3)

    std::vector v{1,2,3,4,5,6};
    return v;

相同
    std::vector v{1,2,3,4,5,6};
    return std::move(v);

...还有一个std::span<int>无法从右值 vector 构造。

之前的行为是尝试移动,如果该移动不可能,则会进行复制。

看起来 gcc 即使在 C++20 模式下也会进行简化的移动。

其中之一可以修复它:

    return (std::vector<int>&) v;
    return static_cast<std::vector<int>&>(v);  // (This seems like the recommended solution)
    return static_cast<decltype((v))>(v);
    return static_cast<decltype(v)&>(v);
    return std::identity{}(v);

    // These two may have slightly different behaviour depending on
    // the constructors of the return type, but work here
    return { v };
    return S<int, std::dynamic_extent>(v);

关于c++ - 在模板化函数中将 std::vector 设置为本地会导致编译失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76737907/

相关文章:

c++ - 使用 if constexpr 时扣除模板参数失败

c++ - 两个指针合法的 c++17 常量表达式之间的区别是什么?

c++ - 来自 std::any 的 std::is_reference

C++:constructor() 和 constructor(void) 的区别

c++ - C++ 模板的声明和定义分离

c++ - 为什么像 "a[i] = i++;"这样的增量操作会导致未定义的行为?

c++ - 在模板调用中将包装器类隐式转换为父类(super class)

c++ - 如何将 std::is_convertible_v 应用于一组可变参数?

c++ - 静态库中的单例类

c++ - VC 2013 与 2015 中的 Lambda 删除器