Вчера довелось заглянуть в cppreference в описание стандартного класса std::reference_wrapper. И взгляд зацепился за показанную там возможную реализацию этого класса:
namespace detail { template <class T> constexpr T& FUN(T& t) noexcept { return t; } template <class T> void FUN(T&&) = delete; } template <class T> class reference_wrapper { public: // types using type = T; // construct/copy/destroy template <class U, class = decltype( detail::FUN<T>(std::declval<U>()), std::enable_if_t<!std::is_same_v<reference_wrapper, std::remove_cvref_t<U>>>() )> constexpr reference_wrapper(U&& u) noexcept(noexcept(detail::FUN<T>(std::forward<U>(u)))) : _ptr(std::addressof(detail::FUN<T>(std::forward<U>(u)))) {} reference_wrapper(const reference_wrapper&) noexcept = default; // assignment reference_wrapper& operator=(const reference_wrapper& x) noexcept = default; // access constexpr operator T& () const noexcept { return *_ptr; } constexpr T& get() const noexcept { return *_ptr; } template< class... ArgTypes > constexpr std::invoke_result_t<T&, ArgTypes...> operator() ( ArgTypes&&... args ) const noexcept(std::is_nothrow_invocable_v<T&, ArgTypes...>) { return std::invoke(get(), std::forward<ArgTypes>(args)...); } private: T* _ptr; }; |
Внимание мое привлекли реализации конструкторов для reference_wrapper. Как-то сурово там все, сходу и не поймешь. Т.е. приблизительно понятно почему так сложно, но вот как именно это должно работать... За пару-тройку минут и не въедешь.
Чуть позже, уже по дороге домой, посредством неспешных размышлений картинка выстроилась, вроде бы все встало на свои места. И как бы и не сложно там все. Хотя и страшно это конечно же выглядит.
Но потом подумалось вот что: а ведь если на собеседовании по C++ у соискателя попросить объяснить почему у предложенной реализации reference_wrapper такие конструкции и как именно это работает, то получится отличный вопрос на знание C++.
Действительно, тут тебе и выбор между шаблоном и не шаблоном, и SFINAE, и std::declval, и оператор запятая, и тип выражения, в котором оператор запятая используется, и про noexcept, и еще раз про noexcept, но уже другой, и std::addressof вместо &, и еще всякое разное по мелочи.
Как по мне, так если человек слабо знает C++, то он толком ничего объяснить не сможет.
Если знания C++ средненькие, как у меня, например, то потихоньку выплывет. Заодно интервьюер сможет послушать как соискатель размышляет в процессе. Это же, типа, очень важно, можно и молодежно, как же без этого ;)
Ну а если перед вами человек, который с C++ на "ты", то для него это вообще проблемы не составит. Может он даже расскажет, как сделать тоже самое более простым и красивым способом (disclaimer: я даже не имею понятия можно ли вообще).
В случае, если требуется еще и знание C++20, то можно попросить переписать шаблонный конструктор посредством концептов.
Короче говоря, если бы мне на собеседовании такой вопрос задали, то это было бы интереснее, чем запрограммировать в онлайне какую-то около олимпиадную задачку. Не говоря уже про банальности о виртуальном деструкторе :)
А потом еще немного подумаешь, и решишь "ну их всех в баню, пойду в [s]прости[/s] rust" )
ОтветитьУдалитьНе потому что сложно, а потому что хочется решать реальные проблемы
Для решения реальных проблем еще 20 лет назад можно было бы уйти в Java. Еще лет за пять до того можно было уйти в FoxPro/Clipper или 1С :)
ОтветитьУдалитьА вот из-за чего реально хочется уйти из C++, так это из-за CMake... :(((
В Java и др. нельзя -- у них gc
ОтветитьУдалитьНу а отсутствие нормальной системы сборки/пакетирования -- это та проблема, которую, видимо, никто и не собирается решать.
Куда важнее ренджи или еще какую ерунду в стандарт протащить, чем сделать систему, в которой пользователь сам будет решать какие ренджи ему нужны.
@night beast:
ОтветитьУдалить> сделать систему, в которой пользователь сам будет решать какие ренджи ему нужны
Мне кажется, что Microsoft со своим vcpkg нужное дело делает.
Хотя сам бы я лично предпочел бы server-less менеджер зависимостей для C++.
> Мне кажется, что Microsoft со своим vcpkg нужное дело делает.
ОтветитьУдалитьнужное. и cmake тоже нужное.
только это все суррогаты.
каждый понимает что надо как-то решать проблему и пытается это делать самостоятельно.
@night beast:
ОтветитьУдалитьCMake редкостное Г, лучше бы его закопать.
А вот почему vcpkg суррогат?
потому что, имхо, нужно стандартное решение на уровне языка
ОтветитьУдалитьпо типу cargo/pip/etc
@night beast:
ОтветитьУдалитьСвежий комментарий на Хабре от Антона Полухина:
"Работа идёт, и она в приоритете для C++26.
Сейчас комитет отошёл от идеи стандартизировать какой-то имеющийся пакетный менеджер или систему сборки. Вместо этого сосредоточились на создании стандартного языка описания зависимостей и сборки. Чтобы с таким файлом описания вы могли собрать проект и с помощью cmake, и с помощью basel, и с помощью conan..."
ну дай бог...
ОтветитьУдалить@night beast
ОтветитьУдалитьАга. Рефлексия и pattern matching тоже давным давно в работе :)