Как стать автором
Обновить

Комментарии 13

Не могли бы вы подсказать, какой именно фрагмент тяжелее всего читать? Я старался использовать привычные обороты русской речи, но, возможно, некоторые предложения действительно следует перефразировать.
Не знаю, у меня от всего текста ощущение, что просто в английской версии взяли и каждое слово заменили на его перевод:
И снова, решение использовать нетипизированное сырое хранилище является ограничением для полной реализации обобщённого размеченного объединения на том же уровне, который можно достичь, реализовав его вручную.
Реализация, основанная на сыром хранилище — хотя и оправдывает свою цену — не выдерживает критики, когда её нагружают до предела.
Ну не русский это язык, имхо.
Подправил эти и ещё некоторые шероховатости в переводе, заодно нашёл и исправил несколько опечаток. Надеюсь, так стало лучше :).
Статья, действительно, хорошая. Хотелось бы сказать, что, кому интересно, — следите ещё за статьями на reddit-е — выкладывается новый и хороший материал. Например, ссылка на оригинал это статьи — была выложена ещё 3 месяца назад.
Спасибо за перевод.
Круто. В копилку ссылокзнаний.
Спасибо за перевод.
Пару вопросов по тексту, если можно.
static constexpr std::size_t alignment_value = std::max({alignof(Types)...});
Я верно понимаю, что в c++14 std::max стало можно использовать в constexpr выражениях?

static_cast<T*>(static_cast<void*>(&_storage))
Почему не reinterpret_cast<T*>(&_storage)? Довольно необычная конструкция прежде ее не видел.
Я верно понимаю, что в c++14 std::max стало можно использовать в constexpr выражениях?

Да, смотрите max (3).
Почему не reinterpret_cast<T*>…

Смотрите здесь. Приведу полный текст статьи:
The C++ standard guarantees the following:

static_casting a pointer to and from void* preserves the address. That is, in the following, a, b and c all point to the same address:

int* a = new int();
void* b = static_cast<void*>(a);
int* c = static_cast<int*>(b);

reinterpret_cast only guarantees that if you cast a pointer to a different type, and then reinterpret_cast it back to the original type, you get the original value. So in the following:

int* a = new int();
void* b = reinterpret_cast<void*>(a);
int* c = reinterpret_cast<int*>(b);

a and c contain the same value, but the value of b is unspecified. (in practice it will typically contain the same address as a and c, but that’s not specified in the standard, and it may not be true on machines with more complex memory systems.

For casting to and from void*, static_cast should be preferred.
a and c contain the same value, but the value of b is unspecified. (in practice it will typically contain the same address as a and c, but that’s not specified in the standard, and it may not be true on machines with more complex memory systems.

For casting to and from void*, static_cast should be preferred.
Это утверждение — неправда, смотрите 5.2.10p7 стандарта (он описывает поведение reinterpter_cast):
An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of type “pointer to T1” is converted to the type “pointer to cv T2”, the result is static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.
Почему не reinterpret_cast<T*>(&_storage)? Довольно необычная конструкция прежде ее не видел.
Бытует мненние, что reinterpret_cast небезопасный и страшный, а static_cast добрый и пушистый, и все проверяет. Поэтому будем везде писать static_cast и никогда не столкнемся с ошибками приведения типов.

На самом деле это не совсем так, и такой код скомпилируется, но работать в общем случае не будет

int main()
{
	int x = 5;
	//double& y = static_cast<double&>(x); -- does not work :(
	//double& y = reinterpret_cast<double&>(x); -- unsafe
	double& y = *static_cast<double*>(static_cast<void*>(&x)); // --perfect

	std::cout << y << '\n';
}
Этот код — UB, потому что нарушает strict aliasing. Но это цветочки (два каста, один из них к void*, выглядит все это крайне подозрительно), как насчет такого доброго и пушистого приведения:
struct A {};
struct B : public A {};

int main()
{
    A x;
    B& y = static_cast<B&>(x);
}

Ну это отсылка к теме приведения через static_cast к void* и обратно. Если два каста будут не в одной строчке, а в разных функциях, то это будет уже не так очевидно.

Но ваш пример тоже хорош, да
Спасибо за статью. Боюсь, что в один момент наступит С++*x, который я уже буду слабо понимать…

P.S. И это... Вы смотрите не туда. :)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории