Re[9]: Вопрос про ссылки - что бы сломалось, если...
От: B0FEE664  
Дата: 11.07.24 10:07
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

BFE>>Сказать, что функция возвращает ссылку, это всё равно, что сказать, что функция возвращает имя.

ЕМ>Э-э-э... А как еще можно более коротко и менее формально сказать "функция возвращает значение ссылочного типа"? В английском термины "reference type" и "reference" в отношении значений тоже эквивалентны.

Неформально можно сказать многое, в том числе, что функция возвращает ссылку, но считать, что при этом на самом деле возвращается некий объект-ссылка — ошибка.
И каждый день — без права на ошибку...
Re[3]: Вопрос про ссылки - что бы сломалось, если...
От: B0FEE664  
Дата: 11.07.24 10:24
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>Получается, проблема таки в синтаксисе — нет механизма переприсвоить ссылку. И это таки баг языка (имхо конечно).

Это не ошибка языка, а так и задумано.

SP>p.s. Кстати, заметьте, насколько в Rust тривиальное определение ссылки. Это просто адрес. А в С++ уже на 10 страниц развели спор об определении.

Вот в Json тоже писали краткие определения, а на практике оказалось, что в результате очень много ошибок о которых авторы не подумали.

отсюда
let a = "объект с данными в куче".to_string();
// объект передан переменной b
// переменная a становится неинициализированной
let b = a;
// ошибка!
let c = a;

В чём смысл такого? Или все такие ошибки отлавливаются на этапе компиляции?
И каждый день — без права на ошибку...
Re[4]: Вопрос про ссылки - что бы сломалось, если...
От: sergii.p  
Дата: 11.07.24 11:12
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, sergii.p, Вы писали:


SP>>Получается, проблема таки в синтаксисе — нет механизма переприсвоить ссылку. И это таки баг языка (имхо конечно).

BFE>Это не ошибка языка, а так и задумано.

понятно, что так и задумано, но мне кажется в долгосрочной перспективе ошиблись.
Сейчас ведь даже нельзя написать что-то типа такого:

template<typename T, typename Pred>
std::optional<T&> find(std::vector<T> const& vec, Pred&& pred);


хотя optional для этого по сути и задумывался.

BFE>Вот в Json тоже писали краткие определения, а на практике оказалось, что в результате очень много ошибок о которых авторы не подумали.


ну а в С++ пример обратный. Перемудрили.

BFE>
BFE>let a = "объект с данными в куче".to_string();
BFE>// объект передан переменной b
BFE>// переменная a становится неинициализированной
BFE>let b = a;
BFE>// ошибка!
BFE>let c = a;
BFE>

BFE>В чём смысл такого? Или все такие ошибки отлавливаются на этапе компиляции?

немного не понял вопроса. Тут же не ссылки. Тут что-то типа такого в переводе на C++

auto a = std::string {"abc"};
auto b = std::move(a);
auto c = std::move(a);


всякие cpp check это тоже отлавливают.
Re[5]: Вопрос про ссылки - что бы сломалось, если...
От: B0FEE664  
Дата: 11.07.24 12:12
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>>>Получается, проблема таки в синтаксисе — нет механизма переприсвоить ссылку. И это таки баг языка (имхо конечно).

BFE>>Это не ошибка языка, а так и задумано.
SP>понятно, что так и задумано, но мне кажется в долгосрочной перспективе ошиблись.
Не, то, чего хочет Shmj не согласуется с принципом бедняка: "Не платить за то, что не используется". Если попробовать полностью описать как должно работать переназначение ссылок, то первым делом сама ссылка станет объектом и будет занимать какую-то память, потом появится подсчёт ссылок и в конечном итоге получится конструкция функционально неотличимая от std::shared_ptr<NotNullPtr<T>>

SP>Сейчас ведь даже нельзя написать что-то типа такого:

SP>
SP>template<typename T, typename Pred>
SP>std::optional<T&> find(std::vector<T> const& vec, Pred&& pred);
SP>

SP>хотя optional для этого по сути и задумывался.
template<typename T, typename Pred>
std::optional<std::reference_wrapper<T>> find(std::vector<T> const& vec, Pred&& pred);

Не подойдёт?

SP>ну а в С++ пример обратный. Перемудрили.

С++ был придумал, развивался и развивается по эволюционной модели развития проекта, что, конечно, несёт с собой отрицательные аспекты.
И каждый день — без права на ошибку...
Re[5]: Вопрос про ссылки - что бы сломалось, если...
От: so5team https://stiffstream.com
Дата: 11.07.24 12:16
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>Сейчас ведь даже нельзя написать что-то типа такого:


SP>
SP>template<typename T, typename Pred>
SP>std::optional<T&> find(std::vector<T> const& vec, Pred&& pred);
SP>


SP>хотя optional для этого по сути и задумывался.


Так ведь здесь вот просто напрашивается:
template<typename T, typename Pred>
T* find(std::vector<T> const & vec, Pred&& pred);


Не зря же optional мимикрирует под указатель.
Re[5]: Вопрос про ссылки - что бы сломалось, если...
От: σ  
Дата: 11.07.24 12:39
Оценка:
SP>>>Получается, проблема таки в синтаксисе — нет механизма переприсвоить ссылку. И это таки баг языка (имхо конечно).
BFE>>Это не ошибка языка, а так и задумано.

SP>понятно, что так и задумано, но мне кажется в долгосрочной перспективе ошиблись.

SP>Сейчас ведь даже нельзя написать что-то типа такого:

SP>
template<typename T, typename Pred>
std::optional<T&> find(std::vector<T> const& vec, Pred&& pred);


Если ты капитально задумаешься о том (и осознаешь) что есть ссылка, то станет понятно, что запись std::optional<T&> не имеет смысла
Re[6]: Вопрос про ссылки - что бы сломалось, если...
От: sergii.p  
Дата: 11.07.24 13:04
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>
BFE>template<typename T, typename Pred>
BFE>std::optional<std::reference_wrapper<T>> find(std::vector<T> const& vec, Pred&& pred);
BFE>

BFE>Не подойдёт?

я уже ел этот кактус, повторно не предлагать

using Map = std::vector<std::string_view>;
using Opt = std::optional<std::reference_wrapper<Map::value_type>>;
 
Opt find(Map& m, std::string_view s)
{
    auto it = std::find(m.begin(), m.end(), s);
    return it == m.end() ? Opt{} : Opt{*it};
}

int main(int argc, char* argv[]) {
    Map vec = {"123", "234"};

    auto tmp = std::string_view{"123"};
    std::cout << find(vec, tmp).value_or(std::ref(tmp)).get();
}


Оно как бы компилируется, но такое количество костылей на единицу строчки неприемлемо.
Re[6]: Вопрос про ссылки - что бы сломалось, если...
От: sergii.p  
Дата: 11.07.24 13:07
Оценка:
Здравствуйте, so5team, Вы писали:

S>Так ведь здесь вот просто напрашивается:

S>
S>template<typename T, typename Pred>
S>T* find(std::vector<T> const & vec, Pred&& pred);
S>


да, приходится так писать. Но это же "теоретически" неверно. Никто выходящий указатель на nullptr проверять не будет, компилятор за этим не проследит. Короче нафига тогда std::optional?
Re[7]: Вопрос про ссылки - что бы сломалось, если...
От: so5team https://stiffstream.com
Дата: 11.07.24 13:29
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>Но это же "теоретически" неверно.


Это смотря с какой теории смотреть.

SP>Никто выходящий указатель на nullptr проверять не будет, компилятор за этим не проследит.


Но ведь так же можно сказать, что и optional на пустоту проверять никто не будет.
Тем не менее код вида:
std::optional<T> r = try_get_object();
if(r) r->do_something();

пишут.

И в этом плане optional по интерфейсу очень похож на указатель.

SP>Короче нафига тогда std::optional?


Если смотреть на std::optional как на объект, который предоставляет место для хранения T, при этом еще и следит за временем жизни T, то получается очень удобная штука.
Не нужно писать самому что-то вроде:
alignas(T) std::byte storage[sizeof(T)];
T * obj = new(storage) T{...};
...
obj->~T();


И если смотреть на std::optional так, то становится понятно, почему нет смысла в optional помещать ссылку. По крайней мере с моей колокольни удобно смотреть так.
Re[8]: Вопрос про ссылки - что бы сломалось, если...
От: reversecode google
Дата: 11.07.24 13:32
Оценка: -1
есть некоторое общее правило С++
если передается указатель
ему можно сделать delete
можно ли в том find сделать delete тому указателю что вернется?
вряд ли
рискованно
опасно
уб
уц
уд
уе
Re[9]: Вопрос про ссылки - что бы сломалось, если...
От: so5team https://stiffstream.com
Дата: 11.07.24 13:43
Оценка: +1
Здравствуйте, reversecode, Вы писали:

R>есть некоторое общее правило С++

R>если передается указатель
R>ему можно сделать delete
R>можно ли в том find сделать delete тому указателю что вернется?

Есть общее правило: писать с выделением предложений знаками препинания, начиная каждое новое предложение с заглавной буквы. Но некоторым альтернативно одаренным на это пох. А на мнение альтернативно одаренных откровенно начхать.

Особенно если эти альтернативно одаренные ведут себя типа как суперпрофи, но при этом не в курсе про правило "никаких голых владеющих указателей"
Re[8]: Вопрос про ссылки - что бы сломалось, если...
От: sergii.p  
Дата: 11.07.24 14:03
Оценка:
Здравствуйте, so5team, Вы писали:

S>Но ведь так же можно сказать, что и optional на пустоту проверять никто не будет.


ага. И эти вопросы я бы хотел задать тем, кто принимал optional в таком виде в стандарт

S>Если смотреть на std::optional как на объект, который предоставляет место для хранения T, при этом еще и следит за временем жизни T, то получается очень удобная штука.


это как бы побочный эффект optional. Не думаю, что создавался для этого. Для меня классическое применение в методах типа find. Во многих языках (Haskell, Rust, Zig) так, но почему-то не в С++.
Re[9]: Вопрос про ссылки - что бы сломалось, если...
От: so5team https://stiffstream.com
Дата: 11.07.24 15:30
Оценка:
Здравствуйте, sergii.p, Вы писали:

S>>Но ведь так же можно сказать, что и optional на пустоту проверять никто не будет.


SP>ага. И эти вопросы я бы хотел задать тем, кто принимал optional в таком виде в стандарт


Для другого вида в стандарт сначала следовало бы принять полноценные алгебраические типы и паттерн-матчинг. Но этого и в C++26, вероятно, не будет. Что уж про C++17 говорить.

S>>Если смотреть на std::optional как на объект, который предоставляет место для хранения T, при этом еще и следит за временем жизни T, то получается очень удобная штука.


SP>это как бы побочный эффект optional.


Ну как бы не совсем, т.к. мы же в рамках C++, в котором доминирует value-семантика. А раз у нас value, значит optional играет роль хранилища для этого value + булевый признак актуальности значения в хранилище.

SP>Для меня классическое применение в методах типа find.


Ну вот в том же Rust есть find для str. Он же не optional с ссылкой внутри возвращает.
Сделайте свою функцию как:

template<typename T, typename Pred>
optional<std::vector<T>::size_type> find(std::vector<T> const & vec, Pred&& pred);


и будете иметь тоже, что и в Rust-е.

SP>Во многих языках (Haskell, Rust, Zig) так, но почему-то не в С++.


Опять же, если сравнивать C++ с другими языками, в которых, во-первых, есть reference-типы и GC, и, во-вторых, есть алгебраические типы и паттерн-матчинг, то там можно делать совсем не так, как в C++ (я про Haskell и Scala). Но в C++ нет ни того, ни другого, приходится выкручиваться.
Re[7]: Вопрос про ссылки - что бы сломалось, если...
От: B0FEE664  
Дата: 11.07.24 18:16
Оценка:
Здравствуйте, sergii.p, Вы писали:

BFE>>
BFE>>template<typename T, typename Pred>
BFE>>std::optional<std::reference_wrapper<T>> find(std::vector<T> const& vec, Pred&& pred);
BFE>>

BFE>>Не подойдёт?

SP>я уже ел этот кактус, повторно не предлагать


  Скрытый текст
SP>
SP>using Map = std::vector<std::string_view>;
SP>using Opt = std::optional<std::reference_wrapper<Map::value_type>>;
 
SP>Opt find(Map& m, std::string_view s)
SP>{
SP>    auto it = std::find(m.begin(), m.end(), s);
SP>    return it == m.end() ? Opt{} : Opt{*it};
SP>}

SP>int main(int argc, char* argv[]) {
SP>    Map vec = {"123", "234"};

SP>    auto tmp = std::string_view{"123"};
SP>    std::cout << find(vec, tmp).value_or(std::ref(tmp)).get();
SP>}
SP>


SP>Оно как бы компилируется, но такое количество костылей на единицу строчки неприемлемо.


Честно говоря я не понял, что вам не нравится и чего хочется.
Я не знаю, для чего задумывался std::optional, но в качестве результата я его ни разу не использовал. Использовал для указания отсутствия данного.
И вообще, если у вас в качестве параметра функтор, то зачем вообще что-то возвращать?

    const std::vector<std::string_view> vec = {"123", "234", "4", "567", "321"};
    unsigned int nCount = 0; // счётчик найденных
    auto fnOut = [&nCount](const auto& x){ std::cout << '\n' << x; ++nCount;}; // вывод и подсчёт
    std::ranges::find_if(
                          vec, // никаких begin/end
                          [
                            n = 2, // искать не больше двух
                            &fn = fnOut // операция над найденным
                          ]
                          (const auto& x) mutable 
                          { 
                             if (x.contains('3')) // только элементы содержащие '3'
                             {
                                --n;  // изменили счётчик
                                fn(x);// применили операцию 
                             }
                             return 0 == n; // условие останова
                           }
                         );
    std::cout << '\n' << "Total: " << nCount << " element(s)";
И каждый день — без права на ошибку...
Re[8]: Вопрос про ссылки - что бы сломалось, если...
От: sergii.p  
Дата: 12.07.24 09:45
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Честно говоря я не понял, что вам не нравится и чего хочется.


auto tmp = std::string_view{"123"};
std::cout << find(vec, tmp).value_or(std::ref(tmp)).get();


    нельзя использовать временный объект. std::ref не конструируется от временного
    приходится заводить бессмысленную переменную tmp
    нужно дополнительно вызывать get()

хочется такого

find(vec, "123").transform(handle).value_or(def_val);


может это и мелочи, но учитывая, что в коде без исключений value_or используется очень часто, то становится блокером
Re[9]: Вопрос про ссылки - что бы сломалось, если...
От: B0FEE664  
Дата: 12.07.24 10:25
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>хочется такого

SP>
SP>find(vec, "123").transform(handle).value_or(def_val);
SP>


SP>может это и мелочи, но учитывая, что в коде без исключений value_or используется очень часто, то становится блокером

#include <utility>
#include <iostream>
#include <string>
#include <optional>
#include <vector>
#include <algorithm>

using Map = std::vector<std::string_view>;
using Opt = std::optional<std::reference_wrapper<Map::value_type>>;
 
const std::string_view& find(Map& m, std::string_view s, const std::string_view& sDefault)
{
    auto it = std::find(m.begin(), m.end(), s);
    return it == m.end() ? sDefault : *it;
}

int main(int argc, char* argv[]) {
    Map vec = {"123", "234"};

    auto tmp = std::string_view{"123"};
    std::cout << find(vec, tmp, "not found");

    return 0;
}


std::optional здесь не нужен.
И каждый день — без права на ошибку...
Re: Вопрос про ссылки - что бы сломалось, если...
От: graniar  
Дата: 13.07.24 19:04
Оценка:
Здравствуйте, Shmj, Вы писали:

S>// как то сделать, чтобы ref1 и ref2 ссылались на одну область памяти


Используй указатели и не ломай мозг надуманными проблемами.
Ссылки нужны только для локального удобства, например


int& ref = some.complicated[lvalue->expression];

if(ref==-1) ref = current_iteration;


А если тебе нужно оперировать адресами используй указатели.

int a = 10;
int b = 20;
int* ref1 = a;
int* ref2 = b;

// как то сделать, чтобы ref1 и ref2 ссылались на одну область памяти

ref1 = ref2;


Сорри, если уже ответили, лень было всю ветку читать.
Re[2]: Вопрос про ссылки - что бы сломалось, если...
От: Shmj Ниоткуда  
Дата: 13.07.24 19:05
Оценка:
Здравствуйте, graniar, Вы писали:

G>Используй указатели и не ломай мозг надуманными проблемами.

G>Ссылки нужны только для локального удобства, например

А как же передача в функцию по ссылке? Это и удобно и память лишний раз не копируется.
Re[3]: Вопрос про ссылки - что бы сломалось, если...
От: graniar  
Дата: 13.07.24 19:27
Оценка: :)
Здравствуйте, Shmj, Вы писали:

S>А как же передача в функцию по ссылке? Это и удобно и память лишний раз не копируется.


Разве что при развертывании инлайн-функции. Но там и указатели прекрасно прооптимизируются. А в нормальном вызове аргумент-ссылка и так передается через стэк как указатель, как же иначе то?
Вобщем не дают ссылки никакого магического преимущества.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.