英文:
How to dereference std::unique_ptr<int[]>?
问题
The operator*
works for std::unique_ptr<std::array<int, 5>>
but not for std::unique_ptr<int[]>
. But why?
来自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]
?我基本上想使调用 transform
在使用 std::unique_ptr<int[]> ptr;
的情况下编译通过。
一个可行的解决方案是:
// ...
auto out{ ptr.get() };
std::ranges::transform(data, out, std::negate{});
for (const auto v : std::span{ out, 5 })
// ...
但是否有其他方法可以在不使用原始指针的情况下完成这个操作?
英文:
The operator*
works for std::unique_ptr<std::array<int, 5>>
but not for std::unique_ptr<int[]>
. But why?
Coming from cppreference:
> These member functions are only provided for unique_ptr for the single objects i.e. the primary template.
Here:
#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");
}
Error message:
<source>:16:17: error: no match for 'operator*' (operand type is 'std::unique_ptr<int [], std::default_delete<int []> >')
16 | auto& out { *ptr };
| ^~~~
How can out
be made bound to int[5]
that is pointed to by ptr
? I basically want to make the call to transform
compile for the case of using a std::unique_ptr< int[] > ptr;
.
One working solution that comes to my mind:
// ...
auto out{ ptr.get() };
std::ranges::transform(data, out, std::negate{});
for (const auto v : std::span{ out, 5 })
// ...
But is there another way of doing this without having to touch raw pointers?
答案1
得分: 3
是否有另一种方法可以在不必接触原始指针的情况下完成这个任务?
在我看来,你当前的解决方案是最优的。
另一种方法可能是通过在每个元素上调用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;
英文:
>Is there another way of doing this without having to touch raw pointers?
Your current solution is far optimal in my opinion.
An alternative might be making a reference-range out of the std::make_unique<int[]>
by calling the std::unique_ptr::operator[]
on each element.
#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;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论