Как разыменовать std::unique_ptr<int[]>?

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 связанным с int[5], на которое указывает ptr? В основном я хочу сделать вызов 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 })
// ...

Но есть ли другой способ сделать это, не касаясь необработанных указателей?

Вы можете использовать []?

Eljay 26.06.2023 00:17

@Элджей С std::transform?

digito_evo 26.06.2023 00:33
operator*() const: эквивалентно *get().
273K 26.06.2023 00:36

Что вы ожидаете от operator* примененного на std::unique_ptr< int[] > возврата?

alfC 26.06.2023 00:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
93
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть ли другой способ сделать это, не касаясь необработанных указателей?

Ваше текущее решение, на мой взгляд, является оптимальным.

Альтернативой может быть создание диапазона ссылок из std::make_unique<int[]> вызовом std::unique_ptr::operator[] для каждого элемента.

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

Смотрите живую демонстрацию на godbolt.org

Другие вопросы по теме