Статья, действительно, хорошая. Хотелось бы сказать, что, кому интересно, — следите ещё за статьями на reddit-е — выкладывается новый и хороший материал. Например, ссылка на оригинал это статьи — была выложена ещё 3 месяца назад.
Спасибо за перевод.
Да интересно, но, наверное, придётся оговариваться, что вот такие имена функций-членов класса — зарезервивованы — и ни в коем случае не используйте их! Так как приоритет у функции-члена — выше. И, действительно, как уже сказали выше — это breaking changes.
(В действительности, ситуация аналогична той же в C++, за той разницей, что C++ позволит вам сделать кучу глупых ошибок и не даёт каких-либо гарантий работы с памятью. Не спорьте со мной по этому поводу, здесь я лишь цитирую других людей, я не знаю C++ в должной степени.)
Мне нравится, как в каждой статье о Rust, упоминается ужасный и неконтролируемый C++ с кучей проблем. В данной ситуации — статья — чисто о Rust — никаких сравнений с C++ — нет, и если Вы (автор оригинальной статьи) что-то, где-то слышали, что, мол C++ «Ужас и боль», то это не значит, что об этом нужно упоминать беспричинно и безаргументно. Просто ужасно надоело этот шаблон: «Вот — язык Х, а в С++ — будут страшные проблемы, если сделать так же». И в 90% приводится код, который на плюсах никто и никогда не пишет.
Нет, он не инклудит сам себя, Вы смотрите файлы в папке \boost\preprocessor\slot.
И файл counter.hpp (который у вас в комментарии) инклудит файл detail\counter.hpp, а вот BOOST_PP_SLOT_CC_*, который в def.hpp, как раз «склеивает» разряды числа.
Файлы (и расположение) одинаковы в 2х версиях буста, которые у меня есть (1.55 и 1.56).
Как, черт побери, работает BOOST_PP_COUNTER?! Даже на stackoverflow ответом на соответствующий вопрос является «magic».
Я не использовал BOOST_PP_COUNTER, но мне стало интересно. Насколько я понял, всё сводится к следующему:
// File counter.hpp
#ifndef COUNTER_H_
#define COUNTER_H_
// Начальное значение
#define COUNTER 0
// Файлик, при включении которого будет происходить
// прибавление еденицы к текущему значению и, вообще,
// вся магия
#define UPDATE_COUNTER() "counter_inc.hpp"
#endif
// File counter_inc.hpp
// Увеличиваем текущее значение,
// сохраняем во временную переменную
#define INC_COUNTER COUNTER + 1
// Удаляем старое значение,
// ниже будет определено новое
#undef COUNTER
// Грубо говоря, вся суть сводится к этому, но
// не так просто: текущее значение @INC_COUNTER
// разбирается на 10 разрядов (смотри
// boost\preprocessor\slot\detail\shared.hpp),
// которые потом собираются вместе в @COUNTER (
// смотри t_1_56_0\boost\preprocessor\slot\detail\counter.hpp):
// # if BOOST_PP_COUNTER_DIGIT_10
// # define BOOST_PP_COUNTER BOOST_PP_SLOT_CC_10(BOOST_PP_COUNTER_DIGIT_10, /*ещё разряды*/ BOOST_PP_COUNTER_DIGIT_1)
// # elif BOOST_PP_COUNTER_DIGIT_9
// ...
//
//
// Т.е. максимальное значение @BOOST_PP_COUNTER состоит
// из 10 разрядов: 999999999.
#if(INC_COUNTER == 0)
# define COUNTER 0
#elif(INC_COUNTER == 1)
# define COUNTER 1
// ...
#endif
// Удаляем временную переменную
#undef INC_COUNTER
Классический Win32 API — это С. До 8й виндовс — паралельно и ненавязчиво было (и есть) очень много API, который доступен через COM. А вот вам Windows Runtime:
WinRT is implemented in the C++ programming language[4] and is object-oriented by design.[4] (Its predecessor, Win32 API is written mostly in the C programming language.[5]) It is an unmanaged application programming interface (API) based on Component Object Model (COM) that allows interfacing from multiple languages, just as COM does
Потому что коллеги вас растерзают за такой код, а сисадмин и менеджер не захотят переходить на C++14 там наверняка где-то внутри бегает пара проблем, связанных с обработкой ссылок.
Боже, какой С++14! Тут, кое-кто, не может на 11й перейти!
Кстати, можете добавить более развёрнутые размышления на эту тему от Sutter-а: Why Not Specialize Function Templates?. Там хорошо разжёвано. Например, указано, что в случае (3) — мы имеем перегрузку функции (second base template, overloads (1)) и что явные специализации не перегружают (Specializations don't overload), отсюда и всё вытекает.
Те кто ответил 3 и 6 могут сегодня потратить на торчание на хабре на полчаса больше рабочего времени чем обычно.
Что-то я запутался, может, наоборот — «меньше»? Ведь, не нужно читать статью до конца. Или — время не потраченное на эту статью — можно потратить на какую-то другую? Но тогда, время «торчания» на хабре не изменится? оО
Так как мне не нравится указывать что-то EmptyList-а.
А если задача состоит только в ограничении типов, которыми можно инстанциировать шаблон, то, как по мне, проще что-то такого:
template<typename T>
void foo(int x, typename std::enable_if</*Проверить, есть ли тип T в каком-то списке типов*/>::type* = NULL)
{
}
template<typename T, typename = typename std::enable_if</**/>::type>
struct Foo
{
};
Это прекрасно работает и не приходится инстанциировать весь набор, а только то, что нужно
Я просто думал, что смогу для себя объяснить это в рамках overload resolution (Вот хорошее видео от Stephan T. Lavavej — Overload Resolution).
Вроде как даже нашёл: 13.3.1.4 Copy-initialization of class by user-defined conversion (n3797)
...the candidate functions are selected as follows:
...When initializing a temporary to be bound to the first parameter
of a constructor that takes a reference to possibly cv-qualified T as its first argument, called with a
single argument in the context of direct-initialization of an object of type “cv2 T”, explicit conversion
functions are also considered…
И 13.3.1 Candidate functions and argument lists:
A defaulted move constructor or assignment operator (12.8) that is defined as deleted is excluded from the
set of candidate functions in all contexts.
Если move-конструктор неявно НЕ сгенерирован, то вызывается copy-constructor
Если move-конструктор явно помечен через delete, то copy-constructor НЕ вызывается
Я окончательно запутался. Пошёл смотреть стандарт :(
Спасибо за перевод.
Мне нравится, как в каждой статье о Rust, упоминается ужасный и неконтролируемый C++ с кучей проблем. В данной ситуации — статья — чисто о Rust — никаких сравнений с C++ — нет, и если Вы (автор оригинальной статьи) что-то, где-то слышали, что, мол C++ «Ужас и боль», то это не значит, что об этом нужно упоминать беспричинно и безаргументно. Просто ужасно надоело этот шаблон: «Вот — язык Х, а в С++ — будут страшные проблемы, если сделать так же». И в 90% приводится код, который на плюсах никто и никогда не пишет.
\boost\preprocessor\slot
.И файл
counter.hpp
(который у вас в комментарии) инклудит файл detail\counter.hpp
, а вотBOOST_PP_SLOT_CC_*
, который вdef.hpp
, как раз «склеивает» разряды числа.Файлы (и расположение) одинаковы в 2х версиях буста, которые у меня есть (1.55 и 1.56).
Я не использовал BOOST_PP_COUNTER, но мне стало интересно. Насколько я понял, всё сводится к следующему:
Так что я бы сказал, что COM — живее всех живых
Боже, какой С++14! Тут, кое-кто, не может на 11й перейти!
second base template, overloads (1)
) и что явные специализации не перегружают (Specializations don't overload
), отсюда и всё вытекает.Что-то я запутался, может, наоборот — «меньше»? Ведь, не нужно читать статью до конца. Или — время не потраченное на эту статью — можно потратить на какую-то другую? Но тогда, время «торчания» на хабре не изменится? оО
Внесу и свой костыль:
Так как мне не нравится указывать что-то
EmptyList
-а.А если задача состоит только в ограничении типов, которыми можно инстанциировать шаблон, то, как по мне, проще что-то такого:
Это прекрасно работает и не приходится инстанциировать весь набор, а только то, что нужно
Вроде как даже нашёл: 13.3.1.4 Copy-initialization of class by user-defined conversion (n3797)
И 13.3.1 Candidate functions and argument lists:
Но это не то, скорее всего
Есть класс (структура, не важно):
В этом случае неявный move-constructor не создаётся (По схеме: дважды Нет).
Должен ли компилироваться следующий код?
Ответ — всё в порядке — компилируется и вызывается копирующий конструктор:
Почему? Я как-то не правильно понимаю когда вызывается copy ctor? (Copy constructors):
Если же явно попросить компилятор сгенерировать move-конструктор, то уже действительно вызывается move-конструктор:
Если же явно запретить компилятору генерировать move-конструктор:
Тогда уже компилятор ругается!
Что получается:
Если move-конструктор неявно НЕ сгенерирован, то вызывается copy-constructor
Если move-конструктор явно помечен через
delete
, то copy-constructor НЕ вызываетсяЯ окончательно запутался. Пошёл смотреть стандарт :(
И ещё вот, например, этот сайт выглядит вот-так:
При открытии в новой вкладке — всё ок.
Было бы не плохо сразу же прогружать первую ссылку…