All streams
Search
Write a publication
Pull to refresh
2
0

User

Send message

Проще читать то, что привычнее.

Привычки -- вещь изменяемая.

а вам нравится

Здесь дело не в "нравится", а в правильности, что ли.
То, что const разрешено выносить за тип и там оставлять -- это нехорошее исключение из правил.

В чистом C можно вообще два раза написать const, и это будет компилироваться (это ссылка). Оба const'а здесь относятся к типу char, косвенно это подтверждается формулировкой предупреждений компиляторов.

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

Если соблюдать это правило, то и ошибок меньше будет допускаться.

А кто там будет страдать от правильного написания -- это проблемы тех страдальцев.

А ведь есть ещё вариант:

Circle const *const c{...};

Вот здесь:

    struct foo* foo = (struct foo*)data;

явного приведения типа не требуется.

https://eel.is/c++draft/gram#key-1.sentence-1

Следует прочесть немного выше о том, что мы вообще читаем:

https://eel.is/c++draft/gram#general-1.sentence-1
https://eel.is/c++draft/gram#general-1.sentence-2

А именно:

This summary of C++ grammar is intended to be an aid to comprehension. It is not an exact statement of the language.

Перевод отсюда:

Это краткое изложение грамматики C++ предназначено для облегчения понимания. Это не точное определение языка.

Суть той части документа, на которую вы сослались:

Это не точное определение языка.

И конкретно тот пункт, ссылку на который вы привели, противоречит следующей главе, находящейся в той части документа, которая является точным определением языка: https://eel.is/c++draft/lex.key

https://godbolt.org/z/K1ErnMMxe

class a { public: void foo() {} };
int main() {
    a a;
    a.foo();
};

Поясните, пожалуйста, что именно демонстрирует данный код.

Вы ведь понимаете, что это — вопрос определений, и что любой человек, примерно представляющий суть разговора, может понять, что «контекстно-зависимое ключевое слово» и «контекстно-зависимый идентификатор» — это одно и то же?

Человек, примерно представляющий суть того, что из себя представляет ключевое слово, понимает, что ключевое слово "изымает" данный идентификатор из тех возможных, которые могут быть использованы в программе для именования сущностей, в отличие от контекстно-зависимого идентификатора.

Проще говоря, переменную с именем class невозможно завести в принципе, потому что class -- это ключевое слово, и все такие идентификаторы в программе трактуются именно как ключевое слово class, и -- никак иначе, а переменную с именем final -- очень даже возможно, как раз по причине того, что final не является ключевым словом.

Более того, в Стандарте прямо указано, что в случае неопределённости, как интерпретировать контекстно-зависимый идентификатор, когда он может быть проинтерпретирован и так, и этак, выбор однозначно должен делаться в пользу обычного идентификатора, то есть, без специального значения (смысла).

Отсюда, в частности, следует, что невозможно определить безымянную структуру так, чтобы она стала final, потому что неопределённость, как интерпретировать final в этом контексте, разрешается, в соответствии со Стандартом, в пользу обычного идентификатора, а не в пользу специального значения (смысла) final, и поэтому следующий код успешно компилируется:

auto
fun() {
	struct final {
	} const s;

	return s;
}

struct s: decltype(fun()) {
};

Более того, я бы сказал, что «контекстно-зависимый идентификатор» субъективно имеет меньше смысла, чем «контекстно-зависимое ключевое слово», ну да ладно.

Если что-то является ключевым словом, то основная семантика данного факта такова: данный идентификатор "изымается" из всего множества возможных идентификаторов, доступных для использования в качестве имён сущностей и становится недоступным для этой цели.

Для final -- это не так. Он -- доступен, причём, всегда.

В этом и была суть моего изначального замечания, потому что я полагал, что автор имеет ввиду именно "изъятие" идентификатора final из множества возможных имён для именования сущностей в программе.

C позволяет опускать int во многих случаях.

А C++?

Статья называется "Ключевое слово «volatile» C/C++".

Это -- один момент.

Второй момент связан с тем, что под if'ом идёт сравнение на меньше/больше знакового с беззнаковым, на что компиляторы как правило выдают предупреждение.

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

С примерами у вас -- не очень.

С примерами контекстно-зависимых ключевых слов, которые могут быть использованы в качестве идентификаторов.

Именно ключевых слов, то есть, таких идентификаторов, в отношении которых в Стандарте прямо и недвусмысленно заявлено, что они "reserved for use as keywords" и/или "unconditionally treated as keywords".

const MAX_COUNT_PEOPLE = 4;

Каков тип этой постоянной?

Ответ на этот вопрос содержится в первом предложении моего ответа, на который вы ответили.

это называется контекстно зависимое ключевое слово

Ключевые слова не могут быть использованы в качестве идентификаторов.

Я использовал здесь final два раза в качестве идентификатора (имя структуры и имя переменной) безо всяких проблем, и ни один из 4-х компиляторов даже не пикнул: https://godbolt.org/z/rKh169Wb3

Если же прочитать нечто, достаточно близкое к оригиналу:

https://en.cppreference.com/w/cpp/keyword

То выяснится, что final среди ключевых слов отсутствует.

Зато он присутствует среди идентификаторов с особым смыслом/значением, который (смысл, то бишь, или значение) они (идентификаторы) имеют лишь в определённых контекстах.
В другом месте https://en.cppreference.com/w/cpp/language/final он описывается как спецификатор.
И нигде он не описывается как ключевое слово.

Специально глянул драфт 2015-го года -- там final описывается в главе 2.10, которая называется Identifiers.

Вот пункт 2 оттуда:

2 The identifiers in Table 2 have a special meaning when appearing in a certain context. When referred to in the grammar, these identifiers are used explicitly rather than using the identifier grammar production. Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier.

Table 2 — Identifiers with special meaning

override final

Думаю, излишне будет уточнять, что Стандарт имеет силу аксиомы, то есть, он -- абсолютен, и если он указывает, что это -- identifier with special meaning, а не ключевое слово, значит, это абсолютно именно так и есть.

Напрашивается вопрос: зачем выдумывать про ключевые слова?

Прежде чем будет достигнута программистская зрелость, неизбежно придётся неоднократно взбираться на пик глупости кривой Даннинга-Крюгера.
То есть, само по себе, хоть это и неприятно, -- это необходимая издержка.
Но в дальнейшем -- всё определяется выбором, который делает человек, оказавшись там.
Выборе, сделанном для того, чтобы научиться не попадать туда больше, или для того, чтобы во чтобы то ни стало каждый раз "казаться правым".

В данный момент вы прилагаете существенные усилия не только для того, чтобы там, на пике глупости, удержаться, но и пытаетесь подпрыгнуть ещё выше, и всё -- для того, чтобы "казаться правым".

То, что вы не проверили, является ли final ключевым словом, или проверили, но специально продолжаете его так называть, как раз и показывает, что выбор вы пока делаете не в сторону зрелости.

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

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

Но возможность изменить свой выбор всегда остаётся.

целое ключевое слово

final -- не ключевое слово, иначе этот код не компилировался бы:

#include <cstdlib>
#include <iostream>

int main() {
	struct final final {
		virtual ~final() final {
			std::cout << __func__ << std::endl;
		}

		virtual operator int() final {
			return EXIT_SUCCESS;
		}
	} final;

	return final;
}

Если у вас уже есть тип и вы его контролируете(он ваш), нет никакого смысла делать addressof

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

А если "контролирующий" уволился?

Да даже если автор -- один.
Через год-другой он уже может забыть о потенциальной проблеме.
Задач как правило и без этого хватает.

не понимаю как это можно называть "существенным"

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

Не проще ли один раз написать std::addressof и забыть о потенциальной проблеме в силу невозможности в этом случае её возникновения, сосредоточившись на задаче, нежели постоянно тратить ресурс мозга на то, чтобы помнить, где и что приходится "контролировать"?

Тем более, что std::addressof не вносит никакого overhead'а, а начиная с C++17, является ещё и constexpr.

Ну и что, что поначалу выглядит непривычно и бросается в глаза?
Язык теперь с каждым новым стандартом меняется существенным образом.
Постоянно появляется непривычное, придётся привыкать.

Ну, и в целом, если подходить философски, операция & здесь используется не в полном, широком смысле операции &, который она имеет в отношении классов, а в узком смысле получения адреса объекта.

С этой точки зрения std::addressof подходит явно лучше, нежели операция &, ибо решает именно эту задачу и ни при каких условиях не может начать решать другую, а за операцией & приходится постоянно следить, как бы, начиная с некоторого незаметного момента, не случилось так, что она начала вдруг решать несколько другую, более широкую задачу, нежели предполагалось изначально.

Из существенного:

Исправленный код:

VltShaderConstData& VltShaderConstData::operator=(VltShaderConstData&& other)
{
  if (this == &other)
  {
    return *this;
  }

Имеет смысл заранее убрать грабли на случай перегрузки (возможно, в будущем) унарной операции &:

VltShaderConstData& VltShaderConstData::operator=(VltShaderConstData&& other)
{
  if (this == std::addressof(other))
  {
    return *this;
  }

Решили, что сами блокировать не будут, но если правительство обяжет, то будут, ибо в отношении правительства они -- люди подневольные.

Действуют они пока, похоже, в полном соответствии с тем, что обещали.

Тогда уже не так:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  return puts("Hello World!");
}

А так:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  return puts("Hello World!") != EOF ? EXIT_SUCCESS : EXIT_FAILURE;
}

Сайт Роскосмоса лежит. Могли бы и не публиковать.

Извне России -- не открывается.
Изнутри -- открывается, причём, очень резво, по https.

Где гарантия того, что цифирки на банковском счете вдруг не станут отрицательными?

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

Да, причём её даже не надо копировать — достаточно узнать как она работает, чтобы сделать самому :D

По этой логике тогда ту же React OS можно было бы признать пиратской копией, но это -- не так.

Возможна ли пиратская копия такой программы?

Ну строго говоря, не совсем. Это только означает, что данный конкретный документ не предъявляет никаких требований.

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

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

Откуда это следует?

Это примерно, как в трудовом кодексе не написано явно, что нельзя убивать коллег в офисе. Но это не означает автоматически, что это делать можно.

По трудовому кодексу -- означает. По трудовому кодексу -- можно. Нельзя -- по другому кодексу.

Если и проводить аналогии с юриспруденцией, то стандарт соответствует совокупности всех кодексов.

Однако, проводя аналогии с юриспруденцией, можно сильно ошибиться.
Куда логичнее проводить аналогии с ближайшими науками, например с математикой.

Information

Rating
Does not participate
Registered
Activity