Re[2]: Структурное связывание
От: Кодт Россия  
Дата: 01.10.23 17:04
Оценка: 34 (3)
К>Интересный приёмчик, может быть, даже потянет на идиому.

https://gcc.godbolt.org/z/5cqYMeWGz

Пусть структура из двух элементов отдаёт только данные, а сопровождающий lock — не отдаёт. Ибо нефиг.
template<class Guard, class Data>
struct guarded {
    Guard g;
    Data d;

    template<size_t I> auto& get() requires (I==0) {
        return d;
    }
    template<size_t I> auto& get() const requires (I==0) {
        return d;
    }
};

namespace std {
template<class G, class D> struct tuple_size<guarded<G,D>> {
    static constexpr size_t value = 1;
};
template<class G, class D> struct tuple_element<0, guarded<G,D>> {
    using type = D&;
};
}  // namespace std


тогда
struct lock {
    lock() { std::cout << "lock!" << std::endl; }
    lock(const lock&) = delete;
    ~lock() { std::cout << "unlock!" << std::endl; }
};

struct value {
    void touch() { std::cout << "touch " << this << std::endl; }
};

int main() {
    value x;
    std::cout << "value " << &x << std::endl;

    using G = guarded<lock,value&>;

    std::cout << "===" << std::endl;
    {
        G{{}, x}.d.touch();
    }
    std::cout << "===" << std::endl;
    {
        auto [y] = G{{}, x};
        y.touch();
    }
    std::cout << "===" << std::endl;

    auto g = [&x]() { return G{{}, x}; };
    {
        auto [y] = g();
        y.touch();
    }
    std::cout << "===" << std::endl;
}


Осталось придумать, как это всё покрасивее обмазать синтаксическим сахаром, — помимо собственно структурного связывания.

Может быть, CTAD прикрутить, поддержать отдельно rvalue и lvalue Data (или обойтись std::ref, например)...
Перекуём баги на фичи!
Структурное связывание
От: B0FEE664  
Дата: 28.09.23 15:50
Оценка: 39 (2)
Придумал задачку.
Что выведет следующая программа:
#include <type_traits>
#include <iostream>
#include <functional>
#include <mutex>


class TS
{
  public:
    TS(int x) : m_x{x}{};
    std::pair<std::lock_guard<std::mutex>, int&> Ref()
    {
        return std::pair<std::lock_guard<std::mutex>, int&>{m_mtx, m_x};
    }
    int GetX() 
    {
        std::lock_guard lock(m_mtx);
        return m_x;
    };
  private:
    std::mutex m_mtx{};  
    int m_x{};
};

int main()
{
    TS ts{1};
    {
      auto [lock, x] = ts.Ref();
      x+=1;
    }
    ts.Ref().second++;
    std::cout << ts.GetX() << std::endl;
    return 0;
}
И каждый день — без права на ошибку...
Re: Структурное связывание
От: andrey.desman  
Дата: 28.09.23 17:59
Оценка: +2
Здравствуйте, B0FEE664, Вы писали:

BFE>Придумал задачку.

А в чем предполагается засада?
Re[8]: Структурное связывание
От: so5team https://stiffstream.com
Дата: 03.10.23 12:21
Оценка: +1 :)
Здравствуйте, andyp, Вы писали:

S>>Ну ахринеть.


A>ну так он в чем-то прав имхо. У всей этой raii-шной истории нет шансов блеснуть в коде из трех строчек. Она ж придумана, чтобы со сложностью бороться, а если сложности нет, то и бороться тут не с чем.


A>Другой вопрос в том, что если из modify() вылетит птичка Т.е. в первую очередь это код с разной семантикой, а не простой и сложный.


Да тут вообще разговора не сложилось, т.к. человек не понимает опасностей преждевременного return (причем не важно, будет ли этот return вставлен при сопровождении кода или же modify будет пулять исключениями).

Если бы понимал, то можно было бы рассказать на пальцах какая именно магия скрывается за строчкой:
std::lock_guard lock{this->mutex};

Там ведь RAII -- это только одна составляющая.

Кроме RAII тут есть еще и шаблоны, ведь std::lock_guard -- это шаблон класса.

А кроме шаблонов тут есть еще и Class template argument deduction (CTAD), т.к. мы указали просто std::lock_guard, а не std::lock_guard<std::mutex>.

И, если в одной простой строчке столько фич C++ сосредоточено, то можно озадачиться следующими вопросами:

— должен ли юниор разбираться в подобных вещах и насколько?

— должны ли мы идти на поводу у юниоров и писать код, в котором не будет ни CTAD, ни шаблонов вообще?

Есть у меня подозрение, что если, во-первых, занижать планку требований к C++ разработчикам и, во-вторых, ориентироваться при написании кода на наименее грамотных и опытных, то затраты на разработку на C++ возрастут многократно. Потому, что добавленные в C++ фичи как раз призваны упростить жизнь программиста, а добровольный от них отказ эту жизнь, напротив, усложнит.

ЗЫ. Можно провести аналогию: приходит вчерашний школьник с минимальными знаниями в области высшей математики в НИИ, где сложными расчетами физических процессов занимаются. И руководитель подразделения, куда этот школьник попал, заявляет: ну все, вычисления с комплексной переменной не используем, а то наш новый юниор этого не поймет.
Re[5]: Структурное связывание
От: σ  
Дата: 29.09.23 08:31
Оценка: 6 (1)
BFE>>>auto [x] = ...; // x — может ссылка, может нет
AD>>Никогда не ссылка. Синоним. Или что-то я упустил. (массивы).
BFE>Что за "Синоним"?
BFE>Выглядит как ссылка, ведёт себя как ссылка:
https://timsong-cpp.github.io/cppwp/n4868/dcl.struct.bind#1.sentence-1
https://timsong-cpp.github.io/cppwp/n4868/dcl.struct.bind#4.sentence-9
Re: Структурное связывание
От: Pzz Россия https://github.com/alexpevzner
Дата: 02.10.23 10:35
Оценка: -1
Здравствуйте, B0FEE664, Вы писали:

BFE>Придумал задачку.

BFE>Что выведет следующая программа:

Фигню какую-нибудь.

А в чем вообще ценность таких задачек? Когда тебе 18, то кажется, что код надо писать, проходя по грани человеческих познаний в области языка программирования. С опытом приходит понимание, что код надо писать так, чтобы любой юниор его прочел и правильно понял. И это гораздо сложнее, на самом деле.

А что выведет именно эта програмка — ну, можно запустить и посмотреть...
Re[6]: Структурное связывание
От: so5team https://stiffstream.com
Дата: 02.10.23 14:48
Оценка: :)
Здравствуйте, Pzz, Вы писали:

S>>Скажите, пожалуйста, какой код проще:


Pzz>Плюс-минус одинаково.


Ну ахринеть.

Как бы мне еще запомнить, что в области C++ вы дуб дубом и ваше мнение по поводу C++ нужно сливать в /dev/null сразу же.
Re[3]: Структурное связывание
От: sergii.p  
Дата: 03.10.23 11:38
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE>Это развитие вот такого подхода.


всё-таки оригинал побезопаснее

auto& data = ts.Ref().second;
++data; // oops
Re[2]: Структурное связывание
От: flаt  
Дата: 28.09.23 20:44
Оценка:
Здравствуйте, andrey.desman, Вы писали:

BFE>>Придумал задачку.

AD>А в чем предполагается засада?

Полагаю, в копировании x, несмотря на возврат по ссылке. С другой стороны, этой фиче сто лет в обед, даром, что в структурное связывание завёрнута в данном примере.

upd: наоборот, копирования нет.
Отредактировано 02.10.2023 18:30 flаt . Предыдущая версия .
Re[3]: Структурное связывание
От: B0FEE664  
Дата: 28.09.23 21:54
Оценка:
Здравствуйте, flаt, Вы писали:

BFE>>>Придумал задачку.

AD>>А в чем предполагается засада?
F>Полагаю, в копировании x, несмотря на возврат по ссылке. С другой стороны, этой фиче сто лет в обед, даром, что в структурное связывание завёрнута в данном примере.

В копировании x? Откуда куда?
И каждый день — без права на ошибку...
Re[3]: Структурное связывание
От: andrey.desman  
Дата: 28.09.23 22:00
Оценка:
Здравствуйте, flаt, Вы писали:

F>Полагаю, в копировании x, несмотря на возврат по ссылке. С другой стороны, этой фиче сто лет в обед, даром, что в структурное связывание завёрнута в данном примере.


Т.е. фишка в том, что кто-то или даже многие подумают, что будет создан lvalue копией значения? Потому что auto без &&.
Re[2]: Структурное связывание
От: B0FEE664  
Дата: 28.09.23 22:05
Оценка:
Здравствуйте, andrey.desman, Вы писали:

BFE>>Придумал задачку.

AD>А в чем предполагается засада?

auto x = ...; // => x не ссылка
[x](){ /* x — не ссылка */ };
auto [x] = ...; // x — может ссылка, может нет

Всё лоГично!
И каждый день — без права на ошибку...
Re[3]: Структурное связывание
От: andrey.desman  
Дата: 28.09.23 22:11
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>auto x = ...; // => x не ссылка

BFE>[x](){ /* x — не ссылка */ };
Да.

BFE>auto [x] = ...; // x — может ссылка, может нет

Никогда не ссылка. Синоним. Или что-то я упустил. (массивы).

BFE>Всё лоГично!

Почти)
Отредактировано 28.09.2023 22:21 andrey.desman . Предыдущая версия . Еще …
Отредактировано 28.09.2023 22:19 andrey.desman . Предыдущая версия .
Re[4]: Структурное связывание
От: B0FEE664  
Дата: 29.09.23 00:04
Оценка:
Здравствуйте, andrey.desman, Вы писали:

BFE>>auto [x] = ...; // x — может ссылка, может нет

AD>Никогда не ссылка. Синоним. Или что-то я упустил. (массивы).
Что за "Синоним"?
Выглядит как ссылка, ведёт себя как ссылка:
#include <type_traits>
#include <iostream>
#include <functional>
#include <mutex>


int main()
{
    int a = 1;
    int b = 2;
    
    std::pair<int&, int&> ab{a,b};

    auto [a_, b_] = ab;
    a_ += 8;

    std::cout << "a=" << a << std::endl;
    std::cout << std::boolalpha;
    std::cout << "std::is_same<int&, decltype(a_)>::value = " << std::is_same<int&, decltype(a_)>::value << std::endl;

    return 0;
}

https://godbolt.org/z/csW6Exnz3


BFE>>Всё лоГично!

AD>Почти)
Так что программа-то напечатает?
И каждый день — без права на ошибку...
Re[5]: Структурное связывание
От: andrey.desman  
Дата: 29.09.23 01:07
Оценка:
Здравствуйте, B0FEE664, Вы писали:

AD>>Никогда не ссылка. Синоним. Или что-то я упустил. (массивы).

BFE>Что за "Синоним"?
Примерно как #define

BFE>Выглядит как ссылка, ведёт себя как ссылка.

Но не ссылка

BFE>Так что программа-то напечатает?

3
Re[6]: Структурное связывание
От: B0FEE664  
Дата: 29.09.23 09:39
Оценка:
Здравствуйте, σ, Вы писали:

BFE>>Что за "Синоним"?

BFE>>Выглядит как ссылка, ведёт себя как ссылка:
σ>https://timsong-cpp.github.io/cppwp/n4868/dcl.struct.bind#1.sentence-1
σ>https://timsong-cpp.github.io/cppwp/n4868/dcl.struct.bind#4.sentence-9

Given the type Ti designated by std​::​tuple_­element<i, E>​::​type

— так это и есть ссылка для std::pair<int&, int&>
И каждый день — без права на ошибку...
Re[7]: Структурное связывание
От: andrey.desman  
Дата: 29.09.23 18:23
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>

BFE>Given the type Ti designated by std​::​tuple_­element<i, E>​::​type

BFE>- так это и есть ссылка для std::pair<int&, int&>

Для самой пары значение. Тут можно поговорить на тему guaranteed copy elision.

Да,еще упустил tuple-like классы, но смысл не меняется. Для них ссылки, но это по сути это то же кроме поддержки битовых полей.
Re: Структурное связывание
От: Кодт Россия  
Дата: 01.10.23 16:26
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Придумал задачку.

BFE>Что выведет следующая программа:

Интересный приёмчик, может быть, даже потянет на идиому.
Но — в чём подвох?

Функция возвращает структуру со ссылочным типом внутри.
Прямой доступ — Ref().second — оперирует со ссылкой, тут ничего непредсказуемого нет.
Структурное связывание — делает теневую копию этой структуры и ссылки на её поля, очень грубо говоря,
auto [lock, x] = ts.Ref();

auto copy = ts.Ref();
auto& lock = copy.first;
auto& x = copy.second;

ссылка на ссылку равна ссылке.
И тоже никаких сюрпризов.
Перекуём баги на фичи!
Re[8]: Структурное связывание
От: B0FEE664  
Дата: 02.10.23 10:15
Оценка:
Здравствуйте, andrey.desman, Вы писали:

BFE>>

BFE>>Given the type Ti designated by std​::​tuple_­element<i, E>​::​type

BFE>>- так это и есть ссылка для std::pair<int&, int&>
AD>Для самой пары значение.
В каком смысле?

AD> Тут можно поговорить на тему guaranteed copy elision.

AD>Да,еще упустил tuple-like классы, но смысл не меняется. Для них ссылки, но это по сути это то же кроме поддержки битовых полей.

Ну как же не меняется?
Вот тут:
    int a = 1;
    int b = 2;
    
    std::pair<int&, int&> ab{a,b};

    auto [a_, b_] = ab;
    a_ += 8;

a_ — это ссылка int&
b_ — это ссылка int&

Согласно приведённой σ ссылке на стандарт,
a_ привязывается к скрытой переменной r1 тип которой int&& или int&&& (-> int&) и которая ссылается на поле скрытой переменной e, а вот e — это копия структуры ab типа std::pair<int&, int&>.
И каждый день — без права на ошибку...
Re[9]: Структурное связывание
От: andrey.desman  
Дата: 02.10.23 10:55
Оценка:
Здравствуйте, B0FEE664, Вы писали:

AD>>Для самой пары значение.

BFE>В каком смысле?

В смысле копии пары.

AD>>Да,еще упустил tuple-like классы, но смысл не меняется. Для них ссылки, но это по сути это то же кроме поддержки битовых полей.

BFE>Ну как же не меняется?

Так и не меняется.

BFE>Согласно приведённой σ ссылке на стандарт,

BFE>a_ привязывается к скрытой переменной r1 тип которой int&& или int&&& (-> int&) и которая ссылается на поле скрытой переменной e, а вот e — это копия структуры ab типа std::pair<int&, int&>.

Я так и написал. О чем спор?
Re[2]: Структурное связывание
От: B0FEE664  
Дата: 02.10.23 12:15
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Интересный приёмчик, может быть, даже потянет на идиому.

Это развитие вот такого подхода.

template<typename T>
class SafeData
{
   public:
      ...
      T Get()
      {
         std::lock_guard<std::mutex> lock(mtx);
         return data;
      }
      void Set(const T& value)
      {
         std::lock_guard<std::mutex> lock(mtx);
         data = value;
      }

      template<class Fn>
      auto Access(Fn&& fnAccess)
      {
         std::lock_guard<std::mutex> lock( mtx );
         return const_access(std::forward<Fn>(fnAccess));
      }

      template<class Fn>
      auto Transform(Fn&& op)
      {
         std::lock_guard<std::mutex> lock( mtx );
         return op(data);
      }
   private:
      std::mutex  mtx;
      T           data;
};


В редких случаях есть желание получить опасный прямой доступ к data не через Access/Transform, а напрямую. Сначала я написал LockGuard друзей SafeData, а потом подумал, что можно обойтись парой функций:
    std::pair<std::lock_guard<std::mutex>, T&> LockWrite()
    {
      return std::pair<std::lock_guard<std::mutex>, int&>{mtx, data};
    }

    std::pair<std::lock_guard<std::mutex>, const T&> LockRead()
    {
      return std::pair<std::lock_guard<std::mutex>, const int&>{mtx, data};
    }


К>Но — в чём подвох?

А нет подвоха.

  Скрытый текст
К>Функция возвращает структуру со ссылочным типом внутри.
К>Прямой доступ — Ref().second — оперирует со ссылкой, тут ничего непредсказуемого нет.
К>Структурное связывание — делает теневую копию этой структуры и ссылки на её поля, очень грубо говоря,
К>
К>auto [lock, x] = ts.Ref();

К>auto copy = ts.Ref();
К>auto& lock = copy.first;
К>auto& x = copy.second;
К>

К>ссылка на ссылку равна ссылке.
К>И тоже никаких сюрпризов.

Для меня просто было неожиданностью, что
auto a = ...
и
auto [b] = ...
так различаются.

Я бы ожидал такое:
auto [b] = ... // копия поля
auto [&b] = ... // ссылка на поле
И каждый день — без права на ошибку...
Re[2]: Структурное связывание
От: B0FEE664  
Дата: 02.10.23 12:31
Оценка:
Здравствуйте, Pzz, Вы писали:

BFE>>Придумал задачку.

BFE>>Что выведет следующая программа:
Pzz>Фигню какую-нибудь.
Да — не, ровно то, что должно, без подвохов.

Pzz>А в чем вообще ценность таких задачек?

Вот, думаю в продакшен добавить...

Pzz>Когда тебе 18, то кажется, что код надо писать, проходя по грани человеческих познаний в области языка программирования.

Pzz> С опытом приходит понимание, что код надо писать так, чтобы любой юниор его прочел и правильно понял. И это гораздо сложнее, на самом деле.
Некое противоречие есть в ваших словах.
Или юниор младше 18, либо ему будет интересно читать такой код.

Pzz>А что выведет именно эта програмка — ну, можно запустить и посмотреть...

Это вам не Паскаль.
И каждый день — без права на ошибку...
Re[3]: Структурное связывание
От: Pzz Россия https://github.com/alexpevzner
Дата: 02.10.23 13:42
Оценка:
Здравствуйте, B0FEE664, Вы писали:

Pzz>> С опытом приходит понимание, что код надо писать так, чтобы любой юниор его прочел и правильно понял. И это гораздо сложнее, на самом деле.

BFE>Некое противоречие есть в ваших словах.
BFE>Или юниор младше 18, либо ему будет интересно читать такой код.

Никакого противоречия нет. Мы пишем код, чтобы решить задачу, а не чтобы блеснуть своими познаниями тонкостей языка. И потом этот код будет кто-то поддерживать. Чем он проще и яснее, тем проще его поддерживать и разбираться с проблемами, в нем или по соседству.

Pzz>>А что выведет именно эта програмка — ну, можно запустить и посмотреть...

BFE>Это вам не Паскаль.

А что, C++ дошел уже до того, что программы на нем и запустить стало невозможно?
Re[4]: Структурное связывание
От: so5team https://stiffstream.com
Дата: 02.10.23 13:54
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Никакого противоречия нет. Мы пишем код, чтобы решить задачу, а не чтобы блеснуть своими познаниями тонкостей языка. И потом этот код будет кто-то поддерживать. Чем он проще и яснее, тем проще его поддерживать и разбираться с проблемами, в нем или по соседству.


Скажите, пожалуйста, какой код проще:

Вот этот:
void c::f() {
  std::lock_guard lock{this->mutex};
  this->data.modify();
}


или вот этот:
void c::f() {
  this->mutex.lock();
  this->data.modify();
  this->mutex.unlock();
}


?
Re[5]: Структурное связывание
От: Pzz Россия https://github.com/alexpevzner
Дата: 02.10.23 14:29
Оценка:
Здравствуйте, so5team, Вы писали:

Pzz>>Никакого противоречия нет. Мы пишем код, чтобы решить задачу, а не чтобы блеснуть своими познаниями тонкостей языка. И потом этот код будет кто-то поддерживать. Чем он проще и яснее, тем проще его поддерживать и разбираться с проблемами, в нем или по соседству.


S>Скажите, пожалуйста, какой код проще:


Плюс-минус одинаково.

И нет, мне не нравится и никогда не понравится, что декларация локальной переменной и уход ее из области видимости обладают глобальными побочными эффектами. Но это — C++-ная идеома, ее все понимают, так что и хрен бы с ней.
Re[3]: Структурное связывание
От: Кодт Россия  
Дата: 02.10.23 16:22
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Для меня просто было неожиданностью, что

BFE>auto a = ...
BFE>и
BFE>auto [b] = ...
BFE>так различаются.

BFE>Я бы ожидал такое:

BFE>auto [b] = ... // копия поля
BFE>auto [&b] = ... // ссылка на поле

На этом основывалась дырка в 17 стандарте, не позволявшая делать захват таких полей в лямбду
auto [x, y] = foo();

[x]() {} ();

В 20 разрешили.

Ну и, конечно же, — да, синтаксис непрозрачный.
Фактически, там
auto hidden = foo();
decltype(auto) x = std::get<0>(hidden);
decltype(auto) y = std::get<1>(hidden);

и, при желании, эти геттеры могут возвращать вообще что угодно.

По красоте, надо было бы делать такой синтаксис
[auto x, auto& y] = foo();

но тогда мы бы сразу попали на то, что результат функции непонятно как сохранять и с каким временем жизни. И как это отразится на времени жизни переменных.
Поэтому своя специфическая логика в этом, конечно, есть.
Перекуём баги на фичи!
Отредактировано 02.10.2023 16:27 Кодт . Предыдущая версия .
Re[4]: Структурное связывание
От: B0FEE664  
Дата: 02.10.23 16:53
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Никакого противоречия нет. Мы пишем код, чтобы решить задачу, а не чтобы блеснуть своими познаниями тонкостей языка. И потом этот код будет кто-то поддерживать. Чем он проще и яснее, тем проще его поддерживать и разбираться с проблемами, в нем или по соседству.

Если в C++ придерживаться определённых ограничений, то разбираться с проблемами не придётся. Одно из таких ограничений: никогда не вызывать lock() у мьютекса вне конструктора.
Фактически в приведённой задаче нет никаких тонкостей языка, а просто использование новых возможностей стандарта C++17, которые делают код проще и понятнее.

Например, вот этот код содержит ошибку:
void c::f() {
  this->mutex.lock();
  this->data.modify();
  this->mutex.unlock();
}

— здесь нет ловушки для исключений, а значит mutex останется залоченным, если modify() бросит исключение.

Pzz>>>А что выведет именно эта програмка — ну, можно запустить и посмотреть...

BFE>>Это вам не Паскаль.
Pzz>А что, C++ дошел уже до того, что программы на нем и запустить стало невозможно?
C, как и C++, это такой язык, что отстрелив себе ногу можно годами бегать не замечая отсутствия ноги, а потом на ровном месте внезапно упасть. Ибо UB — оно такое.
Так что если вам программа что-то напечатала, то это не означает, что и в следующий раз она напечатает ровно тоже самое.
И каждый день — без права на ошибку...
Re[5]: Структурное связывание
От: Pzz Россия https://github.com/alexpevzner
Дата: 02.10.23 17:31
Оценка:
Здравствуйте, B0FEE664, Вы писали:

Pzz>>А что, C++ дошел уже до того, что программы на нем и запустить стало невозможно?

BFE>C, как и C++, это такой язык, что отстрелив себе ногу можно годами бегать не замечая отсутствия ноги, а потом на ровном месте внезапно упасть. Ибо UB — оно такое.
BFE>Так что если вам программа что-то напечатала, то это не означает, что и в следующий раз она напечатает ровно тоже самое.

Ну в целом, да. Хотя Си, он, по крайней мере, простой, в голову вмещается.

Мой пойнт заключался в том, что довольно паршиво тащить в боевой код конструкции, которые трудно понять (или требуется специальная особая квалификация, чтобы их понять). Не уверен, впрочем, что в случае C++ это возможно избежать (хотя код chromium-а, в котором я сейчас понемногу копаюсь, он необъятный, но написан без затей — спасибо гугловцам за это).

Но я не так давно общался с коллегой, пытаясь объяснить, что не надо тащить в прод сложность без нужды. Его пойнт заключался более-менее в том, что "эту программу было трудно писать. Справедливо будет, если ее будет трудно читать".
Re[7]: Структурное связывание
От: andyp  
Дата: 03.10.23 11:52
Оценка:
Здравствуйте, so5team, Вы писали:

S>Ну ахринеть.


ну так он в чем-то прав имхо. У всей этой raii-шной истории нет шансов блеснуть в коде из трех строчек. Она ж придумана, чтобы со сложностью бороться, а если сложности нет, то и бороться тут не с чем.

Другой вопрос в том, что если из modify() вылетит птичка Т.е. в первую очередь это код с разной семантикой, а не простой и сложный.
Re[9]: Структурное связывание
От: andyp  
Дата: 03.10.23 16:09
Оценка:
Здравствуйте, so5team, Вы писали:


S>...И, если в одной простой строчке столько фич C++ сосредоточено, то можно озадачиться следующими вопросами:


S>- должен ли юниор разбираться в подобных вещах и насколько?

S>- должны ли мы идти на поводу у юниоров и писать код, в котором не будет ни CTAD, ни шаблонов вообще?

S>Есть у меня подозрение, что если, во-первых, занижать планку требований к C++ разработчикам и, во-вторых, ориентироваться при написании кода на наименее грамотных и опытных, то затраты на разработку на C++ возрастут многократно. Потому, что добавленные в C++ фичи как раз призваны упростить жизнь программиста, а добровольный от них отказ эту жизнь, напротив, усложнит.


Имхо, судя по лекциям профессиональных учителей С++, CTAD как раз и позиционировался для упрощения жизни новичкам — им вообще можно не париться, что std::lock_guard шаблон. Т.е. понимать фичу, писать своё, её использующее, и пользоваться готовым чужим кодом, использующим фичу — три разные вещи и, по крайней мере, в задумке новичкам должно быть проще использовать уже готовые компоненты, написанные с помощью этой фичи.

S>ЗЫ. Можно провести аналогию: приходит вчерашний школьник с минимальными знаниями в области высшей математики в НИИ, где сложными расчетами физических процессов занимаются. И руководитель подразделения, куда этот школьник попал, заявляет: ну все, вычисления с комплексной переменной не используем, а то наш новый юниор этого не поймет.


Ну это стрёмный конечно поход, но очень широко распространенный. Полно внутриконторских гайдлайнов, ограничивающих использование тех или иных фич в языке. Я даже не могу кого-то в этом сильно винить — людям надо выкатывать работающий код с теми программистами, которые у них есть, бюджета и времени на дополнительное обучение у них тоже нет. Им виднее
Re[5]: Структурное связывание
От: andyp  
Дата: 03.10.23 16:17
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Например, вот этот код содержит ошибку:

...
BFE>- здесь нет ловушки для исключений, а значит mutex останется залоченным, если modify() бросит исключение.

Я бы это так уж сразу ошибкой не назвал. Почему бы не придержать нити, ломящиеся к сломанному ресурсу на мьютексе, пока текущая нить не поймает исключение и не починит ресурс? После этого и мьютекс отпустить можно. Имхо, это может вполне себе желаемым поведением быть.
Отредактировано 03.10.2023 16:18 andyp . Предыдущая версия .
Re[10]: Структурное связывание
От: so5team https://stiffstream.com
Дата: 03.10.23 16:59
Оценка:
Здравствуйте, andyp, Вы писали:

A>Имхо, судя по лекциям профессиональных учителей С++, CTAD как раз и позиционировался для упрощения жизни новичкам — им вообще можно не париться, что std::lock_guard шаблон. Т.е. понимать фичу, писать своё, её использующее, и пользоваться готовым чужим кодом, использующим фичу — три разные вещи и, по крайней мере, в задумке новичкам должно быть проще использовать уже готовые компоненты, написанные с помощью этой фичи.


Я все-таки очень надеюсь, что CTAD вводили для того, чтобы придать большей гибкости языку. Грубо говоря, чтобы можно было писать так:
template<typename Obj>
void modify(Obj & obj) {
  std::lock_guard lock{obj.lock_}; // ХЗ что там за тип mutex-а, но нам фиолетово.
  ...
}

вместо
template<typename Obj>
void modify(Obj & obj) {
  std::lock_guard< std::decay_t<decltype(obj.lock_)> > lock{obj.lock_}; // ХЗ что там за тип mutex-а,
                                                                        // но приходится выяснять это
                                                                        // чтобы удовлетворить компилятор.
  ...
}


Или же: было так:
class data_holder {
  std::mutex lock_;
  ...
public:
  void update(int x) {
    std::lock_guard lock{lock_};
    ...
  }
  int get() {
    std::lock_guard lock{lock_};
    return ...;
  }
};

а в один прекрасный момент решили заменить std::mutex на some_spin_lock, и поменяли только одну строку:
class data_holder {
  some_spin_lock lock_;
  ...
  // Все остальное остается без изменений.
};


S>>ЗЫ. Можно провести аналогию: приходит вчерашний школьник с минимальными знаниями в области высшей математики в НИИ, где сложными расчетами физических процессов занимаются. И руководитель подразделения, куда этот школьник попал, заявляет: ну все, вычисления с комплексной переменной не используем, а то наш новый юниор этого не поймет.


A>Ну это стрёмный конечно поход, но очень широко распространенный. Полно внутриконторских гайдлайнов, ограничивающих использование тех или иных фич в языке. Я даже не могу кого-то в этом сильно винить — людям надо выкатывать работающий код с теми программистами, которые у них есть, бюджета и времени на дополнительное обучение у них тоже нет. Им виднее


Мне казалось, что гайдлайны стремятся запрещать потенциально опасные вещи, например:

* исключения, т.к. дорого и непредсказуемо;
* динамическую память после фазы инициализации, т.к. дорого и непредсказуемо;
* рекурсию, т.к. в случае ошибки исчерпаем стек;
* while(true), т.к. в случае ошибки оказываемся в бесконечном цикле

или же вещи из свежих стандартов т.к. нужно оглядываться на старые компиляторы.

Т.е. во вменяемых гайдлайнах во главу угла ставится рациональное зерно и объективные критерии.

А вот "чтобы даже юниор разобрался" так себе критерий, имхо.
Re[11]: Структурное связывание
От: andyp  
Дата: 03.10.23 23:51
Оценка:
Здравствуйте, so5team, Вы писали:

S>Я все-таки очень надеюсь, что CTAD вводили для того, чтобы придать большей гибкости языку. Грубо говоря, чтобы можно было писать так...


Да я в целом согласен, что и опытным разработчикам полезно будет, но останусь при мнении, что задумано это для упрощения жизни новичкам. Уж больно много на эту тему разговоров последнее время было. Про новый чистый простой язык, struggling to get out. Да все не вылазит он никак, каждая "упрощающая" фича идёт с вагоном своих особенностей. Имхо, люди стараются, но как-то получается не очень.

S>Мне казалось, что гайдлайны стремятся запрещать потенциально опасные вещи, например...


Видел как вообще шаблоны запрещали под предлогом code bloat. Ну вот такие представления у некоторых о потенциальной опасности. И ведь не возразишь, из шаблонов действительно код генерится. STL — частая жертва, ибо Степанов всякой фигни намутил (тут идут пара примеров инвалидации итераторов или ещё чего просто ужасного), а вот вам наш кривой велик, на нем езжайте. При чем велик реально кривой. Тут уж на кого нарвешься.
Re[9]: Структурное связывание
От: reversecode google
Дата: 04.10.23 00:19
Оценка:
CTAD ввели с с++17
многие при многие компании все еще сидять на с++11
а некоторые почему то все еще на с++14, хотя я бы сказал он был версией фиксов для 11

тут не ожиданно даже в нвидии
https://old.reddit.com/r/cpp/comments/16xr6v6/c_jobs_q4_2023/k35tiby/

Technologies: C++14 (primary) and python (scripting, automation, CI) on Linux (Qnx on-vehicle). Bonus points if you know Bazel.


вообще для себя если я знаю что проект дальше виндовс линукс-64 не будет и не планируется
то еще можно с++20/23 взять и поюзать CTAD для тех же локов
но если я предполагаю что все таки может придеться в каком то будущем и для чего то аля арм собирать
то уже и вручную поставлю те же параметры шаблона в мютексе
бегать обновлят тулчейны и пересобрать всякие контриб библиотеки для проекта оно напрягает знаете больше чем удобновство языка

и вообще по наблюдениям на последние 17/20 версии только всякие hft ко переползают
у них там прям constexpr/consteval головного мозга

остальные если кодобаза старая то могут так же сидеть все еще на 11 версии

так что понятие новички не новички слишком притянуто
Re[12]: Структурное связывание
От: so5team https://stiffstream.com
Дата: 04.10.23 04:26
Оценка:
Здравствуйте, andyp, Вы писали:

S>>Мне казалось, что гайдлайны стремятся запрещать потенциально опасные вещи, например...


A>Видел как вообще шаблоны запрещали под предлогом code bloat.


Так ведь когда-то давно так и было, на заре появления поддержки шаблонов в компиляторах. Быстро исправили, но "осадочек остался"

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

В общем, полагаю, мы тут друг друга поняли и можем разве что посетовать на то, что ну вот так вот получается. А спора не получится, т.к. не о чем
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.