Здравствуйте, N. I., Вы писали:
NI>По данному же топику видно, что товарищ пытается делать какие-то умозаключения, не вникая в смысл основных терминов и жонглируя ими как попало. До тех пор, пока он не изменит свой подход, объяснять ему что-либо, скорее всего, бесполезно.
А, по-моему, у него нет намерений с вами спорить. У вас нет необходимости его переубеждать, просто помогите разобраться, он будет благодарен. И не только он.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, N. I., Вы писали: BFE>>В соответствии с этим принципом, что из нижепреведённого сообщения об ошибке является названием типа?:
Скрытый текст
BFE>>
NI>cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
BFE>>Вот это тип: BFE>>
NI>non-const lvalue reference of type 'int&'
BFE>>или нет? BFE>>А это: BFE>>
NI>rvalue of type 'int'
BFE>>?
NI>Разве в самом сообщении об ошибке недостаточно ясно указано, что там относится к типам?
Недостаточно.
Почему, например, non-const lvalue reference of type 'int&', а не non-const lvalue reference of type 'int' ? NI>
prog.cc: In function 'int main()':
NI>prog.cc:6:29: error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
NI> 6 | int &lvalue_ref = rvalue();
NI> | ~~~~~~^~
NI>prog.cc:7:30: error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'
NI> 7 | int &&rvalue_ref = lvalue();
NI> | ~~~~~~^~
NI>По-моему, яснее уже некуда...
Ну я не знаю. В стандарте написано по другому:
typedef int& A;
const A aref = 3;
// ill-formed; lvalue reference to non-const initialized with rvalue
The type of aref is “lvalue reference to int”, not “lvalue reference to const int”.
На мой взгляд, то , что взято в кавычки: “lvalue reference to int” является названием типа. Поэтому, на мой взгляд, ваша интерпретация типов не верна. Я ошибаюсь? Где?
Скрытый текст
9.2.3.2/1 References
In a declaration T D where D has either of the forms
& attribute-specifier-seq opt D1
&& attribute-specifier-seq opt D1
and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T”, then the type of the
identifier of D is “derived-declarator-type-list reference to T”. The optional attribute-specifier-seq appertains
to the reference type. Cv-qualified references are ill-formed except when the cv-qualifiers are introduced
through the use of a typedef-name (9.1.3, 12.1) or decltype-specifier (9.1.7.2), in which case the cv-qualifiers
are ignored. [Example:
typedef int& A;
const A aref = 3;
// ill-formed; lvalue reference to non-const initialized with rvalue
The type of aref is “lvalue reference to int”, not “lvalue reference to const int”. — end example] [Note:
A reference can be thought of as a name of an object. — end note] A declarator that specifies the type
“reference to cv void” is ill-formed.
2 A reference type that is declared using & is called an lvalue reference, and a reference type that is declared
using && is called an rvalue reference. Lvalue references and rvalue references are distinct types. Except
where explicitly noted, they are semantically equivalent and commonly referred to as references.
Здравствуйте, N. I., Вы писали:
σ>>>Для инициализации ссылок важен не только тип, но и value category. BFE>>Т.е. вы хотите сказать, что два объекта одного и того же типа не являются взаимозаменяемыми? NI>Сказанное выше относилось к выражениям, а не объектам.
А вопрос был про объекты, а не выражения.
BFE>>Поясню. BFE>>Допустим у меня есть два объекта a1 и a2 типа int. Вы утверждаете, что нельзя один объект, скажем a1, заменить другим объектом — a2, не смотря на то, что эти два объекта одинакового типа. Вам не кажется это странным? Т.е. теперь, по вашему мнению, поведение объекта не определяется его типом?
NI>Для начала тебе надо уяснить, что такое "объект", что такое "выражение", и чем одно отличается от другого. Без понимания этих терминов дальше ты не продвинешься.
Объект — это то, что занимаете некоторую память, имеет время жизни и тип.
Выражение — это некая последовательность символов составленная по определённым правилам служащая для манипуляций и доступа к объектам.
Но вы забыли ещё упомянуть третью сущность — ссылку. Ссылка не является не объектом и не является выражением. Она может рассматриваться как нечто ссылающиеся на объект, например как имя объекта.
NI>В общем случае возможность инициализации ссылки неким инициализатором зависит от трёх характеристик выражения, используемого в качестве данного инициализатора: тип, value category и принадлежность к bit-field. Ни value category, ни принадлежность к bit-field не являются частью типа — это отдельные характеристики.
Отдельные характеристики чего?
Если value category не является частью типа, то почему в стандарте написано так:
A reference type that is declared using & is called an lvalue reference, and a reference type that is declared using && is called an rvalue reference.
Указанные 'lvalue' и 'rvalue' не являются частью названия типа? Откуда это следует? Или lvalue reference — это не тип, а просто название ссылки?
Вот, например, вы пишите: NI>Например, lvalue reference to int можно инициализировать посредством non-bit-field lvalue of type int, но нельзя инициализировать посредством rvalue of type int или bit-field of type int:
"lvalue reference to int" — что это? Тип? Название? Категория?
B0FEE664:
NI>>Разве в самом сообщении об ошибке недостаточно ясно указано, что там относится к типам? BFE>Недостаточно. BFE>Почему, например, non-const lvalue reference of type 'int&', а не non-const lvalue reference of type 'int' ?
В данном случае речь идёт о типе ссылки как самостоятельной сущности, а не типе выражения, которое можно получить, используя имя lvalue_ref в качестве id-expression. Как самостоятельная сущность, ссылка имеет ссылочный тип.
BFE>Ну я не знаю. В стандарте написано по другому: BFE>
BFE>typedef int& A;
BFE>const A aref = 3;
BFE>// ill-formed; lvalue reference to non-const initialized with rvalue
BFE>The type of aref is “lvalue reference to int”, not “lvalue reference to const int”.
BFE>На мой взгляд, то , что взято в кавычки: “lvalue reference to int” является названием типа.
“lvalue reference to int” и “int &” обозначают один и тот же тип. Первое — это название типа прописью, а второе — запись того же типа по правилам синтаксиса языка C++. (неужели ещё и это надо объяснять? )
BFE>Поэтому, на мой взгляд, ваша интерпретация типов не верна. Я ошибаюсь? Где?
Я не вижу какой-либо причинно-следственной связи в твоём рассуждении.
Здравствуйте, B0FEE664, Вы писали:
BFE>Ну я не знаю. В стандарте написано по другому: BFE>
BFE>typedef int& A;
BFE>const A aref = 3;
BFE>// ill-formed; lvalue reference to non-const initialized with rvalue
BFE>The type of aref is “lvalue reference to int”, not “lvalue reference to const int”.
BFE>На мой взгляд, то , что взято в кавычки: “lvalue reference to int” является названием типа. Поэтому, на мой взгляд, ваша интерпретация типов не верна. Я ошибаюсь? Где?
Я попробую дать объяснение, как я это понимаю, да простят мне гуру вероятные неточности.
Важно четко понимать смысл таких сущностей как "тип", "выражение" и "объект" и их взаимоотношения. Согласно 6.9:
Types describe objects (4.5), references (11.3.2), or functions (11.3.5).
Заметьте, о выражениях пока ни слова.
Идем дальше: "6.10 Lvalued and rvalues". "Expressions are categorized according to the taxonomy." И далее идет хорошо известная всем картинка:
Из которой понятно, что все эти страшные слова "glvalue", "prvalue", "xvalue", etc — это категории выражений. и чтобы установить мостик между понятиями "тип" и "выражение" нам нужно найти связь между выражениями и теми сущностями, которые описывают типы (objects, references functions). И связь эта находится тут же, прямо под картинкой:
(1.1) — A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function.
(1.2) — A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears.
(1.3) — An xvalue is a glvalue that denotes an object or bit-field whose resources can be reused (usually because it is near the end of its lifetime)...
(1.4) — An lvalue is a glvalue that is not an xvalue.
(1.5) — An rvalue is a prvalue or an xvalue.
Таким образом, когда мы говорим о типе выражения мы всегда подразумеваем тип объекта или ссылки, которые сопоставлены данному выражению, прямо или косвенно, не забывая при этом о категории самого выражения.
Возвращаясь к примеру:
typedef int& A;
const A aref = 3;
// ill-formed; lvalue reference to non-const initialized with rvalue
The type of aref is “lvalue reference to int”, not “lvalue reference to const int”.
Мы говорим, что здесь присутствуют: неконстантная lvalue ссылка aref, имеющая тип int&. И prvalue выражение '3', вычисление которого инициализирует объект типа int. Или проще — prvalue типа int — я бы так сказал и не парился. Ну и понятно, что prvalue не может быть связано с неконстантной lvalue ссылкой, поэтому компилятор ругается.
--
Не можешь достичь желаемого — пожелай достигнутого.
Тут такой вопрос.
Допустим, есть указатель на int, реально указывающий на объект типа int.
Мы его кастуем к указателю на unsigned int, разыменовываем и читаем значение (lvalue-to-rvalue conversion).
Тип prvalue понятно — unsigned int. А тип value какой?
Из более-менее релевантного что нашёл это одна невнятная фраза > For other objects, the interpretation of the values found therein is determined by the type of the expressions ([expr.compound]) used to access them.
Здравствуйте, N. I., Вы писали:
NI>“lvalue reference to int” и “int &” обозначают один и тот же тип. Первое — это название типа прописью, а второе — запись того же типа по правилам синтаксиса языка C++. (неужели ещё и это надо объяснять? )
Ок. Хорошо. “lvalue reference to int” — обозначает тип ссылки. Замечательно. Тогда в выражении:
int &lvalue_ref = rvalue();
lvalue_ref — это ссылка типа “lvalue reference to int”.
Тогда смотрим на вторую часть сообщения:
cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
Вы меня уверяете, что rvalue — это тип выражения. Так? Если так, то вы хотите сказать, что ссылка привязывается (bind) к выражению, а не к объекту?
B0FEE664:
σ>>>>Для инициализации ссылок важен не только тип, но и value category. BFE>>>Т.е. вы хотите сказать, что два объекта одного и того же типа не являются взаимозаменяемыми? NI>>Сказанное выше относилось к выражениям, а не объектам. BFE>А вопрос был про объекты, а не выражения.
Если речь про этот вопрос
Если n и +A::TIMEOUT имеют одинаковый тип, то почему мы имеем разницу в поведении?
то в данном случае разница имеет место быть из-за различия value category выражений n и +A::TIMEOUT.
NI>>В общем случае возможность инициализации ссылки неким инициализатором зависит от трёх характеристик выражения, используемого в качестве данного инициализатора: тип, value category и принадлежность к bit-field. Ни value category, ни принадлежность к bit-field не являются частью типа — это отдельные характеристики. BFE>Отдельные характеристики чего?
Выражения (внимательно читай предшествующее предложение)
BFE>Указанные 'lvalue' и 'rvalue' не являются частью названия типа?
"lvalue reference" и "lvalue" — это разные понятия. Первое — это разновидность ссылок или ссылочный тип (в зависимости от контекста использования), второе — разновидность выражений.
BFE>Или lvalue reference — это не тип, а просто название ссылки?
В зависимости от контекста употребления, "lvalue reference" может означать как ссылочный тип (если речь идёт о типе), так и ссылку как сущность ссылочного типа.
BFE>Вот, например, вы пишите: NI>>Например, lvalue reference to int можно инициализировать посредством non-bit-field lvalue of type int, но нельзя инициализировать посредством rvalue of type int или bit-field of type int: BFE>"lvalue reference to int" — что это? Тип? Название? Категория?
В данном контексте это сущность, имеющая ссылочный тип. Как, по-твоему, можно инициализировать тип, название или категорию? Включи уже мозг, наконец...
Здравствуйте, rg45, Вы писали:
R>Мы говорим, что здесь присутствуют: неконстантная lvalue ссылка aref, имеющая тип int&. И prvalue выражение '3', вычисление которого инициализирует объект типа int. Или проще — prvalue типа int — я бы так сказал и не парился. Ну и понятно, что prvalue не может быть связано с неконстантной lvalue ссылкой, поэтому компилятор ругается.
Я выделил мне не понятное. До этой темы я считал, что вычисление prvalue в данном случае должно давать временный объект типа int&&, т.е. rvalue reference, которую к lvalue reference привязать нельзя (но можно к const lvalue reference), в отличии от объекта типа int, который легко привязывается к lvalue reference:
Здравствуйте, B0FEE664, Вы писали:
R>>Мы говорим, что здесь присутствуют: неконстантная lvalue ссылка aref, имеющая тип int&. И prvalue выражение '3', вычисление которого инициализирует объект типа int. Или проще — prvalue типа int — я бы так сказал и не парился. Ну и понятно, что prvalue не может быть связано с неконстантной lvalue ссылкой, поэтому компилятор ругается.
BFE>Я выделил мне не понятное. До этой темы я считал, что вычисление prvalue в данном случае должно давать временный объект типа int&&, т.е. rvalue reference, которую к lvalue reference привязать нельзя (но можно к const lvalue reference)...
Времменный объект — да, только типа int а не int&&. Рассмотрим другой пример:
int&& foo();
// . . .int&& a = 42;
int&& b = foo();
В обоих слуючаях — привязка к rvalue ссылкам. Только в первом случае prvalue и временный объект типа int, а во втором — xvalue, без всякого временного объекта (glvalue that denotes an object whose resources can be reused).
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, N. I., Вы писали:
BFE>>Вы меня уверяете, что rvalue — это тип выражения. Так? NI>Ткни пальцем, где я такое говорил?
σ писал, что rvalue — это класс выражений. Он прав, потому что в стандарте так и написано.
BFE>>Если так, то вы хотите сказать, что ссылка привязывается (bind) к выражению, а не к объекту? NI>Binding to an expression — это неформальная фигура речи, обозначающая привязку к объекту или функции, что является результатом данного expression.
Ну, тогда я повторю свой вопрос: какой тип у объекта полученного в результате вычисления rvalue?
Здравствуйте, σ, Вы писали:
BFE>>объект типа int&& σ>У объекта не может быть ссылочного типа в принципе.
Какой тип у результата выражения n + 1, если n типа int?
B0FEE664:
BFE>Здравствуйте, N. I., Вы писали:
BFE>>>Вы меня уверяете, что rvalue — это тип выражения. Так? NI>>Ткни пальцем, где я такое говорил? BFE>σ писал, что rvalue — это класс выражений.
Под классом выражений он явно не имел в виду тип выражения.
BFE>>>Если так, то вы хотите сказать, что ссылка привязывается (bind) к выражению, а не к объекту? NI>>Binding to an expression — это неформальная фигура речи, обозначающая привязку к объекту или функции, что является результатом данного expression.
BFE>Ну, тогда я повторю свой вопрос: какой тип у объекта полученного в результате вычисления rvalue?
Зависит от rvalue и версии стандарта. В случае C++11/14 у prvalue скалярного типа (например, int) результирующего объекта вообще нет. Например, литерал 42 вычисляется в pure value, для которого никаких объектов не создаётся. Если таким prvalue инициализируется ссылка, то временный объект создаётся в контексте её инициализации (самому же prvalue при этом никаких объектов не сопоставляется).
В случае C++17 prvalue скалярного типа может иметь результирующий объект, а может и не иметь, в зависимости от контекста. У prvalue типа void результирующего объекта не может в принципе.
Здравствуйте, σ, Вы писали:
BFE>>>>объект типа int&& σ>>>У объекта не может быть ссылочного типа в принципе. BFE>>Какой тип у результата выражения n + 1, если n типа int? σ>int?
если считать, что int, то я повторю свой пример:
void foo(int&& n){}
int main()
{
int n = 3;
foo(n); // мы точно знаем, что у n тип int. ошибка компиляции.
foo(1 + n); // ошибки компиляции нет, значит результат вычисления (1 + n) - не int.
}
Я полагаю, что результат вычисления имеет тип int&&. Почему это не так?
Здравствуйте, B0FEE664, Вы писали:
BFE>>>объект типа int&& σ>>У объекта не может быть ссылочного типа в принципе. BFE>Какой тип у результата выражения n + 1, если n типа int?
int, конечно же, не int&&. Рассмотри для сравнения два выражения: n + 1, и, например, std::move(n). Оба выражения — rvalue. Но только первое — это prvalue, которое может быть преобразовано во временный объект, а второе — xvalue, которое уже "denotes an object" и создание временного объекта не требуется.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, B0FEE664, Вы писали:
BFE>если считать, что int, то я повторю свой пример: BFE>
BFE>void foo(int&& n){}
BFE>int main()
BFE>{
BFE> int n = 3;
BFE> foo(n); // мы точно знаем, что у n тип int. ошибка компиляции.
BFE> foo(1 + n); // ошибки компиляции нет, значит результат вычисления (1 + n) - не int.
BFE>}
BFE>
BFE>Я полагаю, что результат вычисления имеет тип int&&. Почему это не так?
Потому, что выражение n — это lvalue типа int, (whose evaluation determines the identity of an object), которое не может быть приязано к rvalue ссылке.
--
Не можешь достичь желаемого — пожелай достигнутого.