c++ 如何解引用std::unique_ptr< int[]>?

ct2axkht  于 2023-07-01  发布在  其他
关注(0)|答案(1)|浏览(122)

operator*适用于std::unique_ptr<std::array<int, 5>>,但不适用于std::unique_ptr<int[]>。但为什么呢?
来自cppreference
这些成员函数仅为单个对象的unique_ptr提供,即主模板。
这里:

#include <vector>
#include <memory>
#include <algorithm>
#include <functional>
#include <fmt/core.h>

int main()
{
    std::vector<int> data { 1, 2, 3, 4, 5 };

    // auto ptr { std::make_unique_for_overwrite<std::array<int, 5> >() };
    auto ptr{ std::make_unique_for_overwrite<int[]>(5) };
    if (ptr == nullptr) return 1;
    auto& out{ *ptr }; // does not compile for <int[]>
    std::ranges::transform(data, std::begin(out), std::negate{});

    for (const auto v : out)
        fmt::print("{} ", v);
    fmt::print("\n");
}

错误信息:

<source>:16:17: error: no match for 'operator*' (operand type is 'std::unique_ptr<int [], std::default_delete<int []> >')
   16 |     auto& out { *ptr };
      |                 ^~~~

如何将out绑定到ptr所指向的int[5]?对于使用std::unique_ptr< int[] > ptr;的情况,我基本上想对transform进行编译调用。
我想到了一个可行的解决方案:

// ...
auto out{ ptr.get() };
std::ranges::transform(data, out, std::negate{});

for (const auto v : std::span{ out, 5 })
// ...

但是,有没有其他方法可以做到这一点,而不必接触原始指针?

zxlwwiss

zxlwwiss1#

有没有其他方法可以做到这一点,而不必接触原始指针?
在我看来,你目前的解决方案是最佳的。
另一种方法可能是通过在每个元素上调用std::unique_ptr::operator[]来在std::make_unique<int[]>之外创建一个引用范围。

#include <ranges>
#include <memory>
#include <algorithm>

std::vector<int> data{ 1, 2, 3, 4, 5 };
auto ptr{ std::make_unique<int[]>(5) };

auto range = std::views::iota(0u, std::size(data))
      | std::views::transform([&ptr](auto idx) -> int& { return ptr[idx]; });

std::ranges::transform(data, std::begin(range), std::negate{});

for (const auto v : range)
    std::cout << v;

See live demo in godbolt.org

相关问题