Re[9]: Вывод лямбды
От: Сыроежка  
Дата: 16.08.12 12:12
Оценка: -1
Здравствуйте, Balthasar, Вы писали:

B>Здравствуйте, Сыроежка, Вы писали:


С>>Выполните, пожалуйста, сначала очень простой код



С>>
С>>#include <iostream>

С>>int f() { return 0; }

С>>int main()
С>>{
С>>   std::cout << f;
С>>}
С>>


С>>Посмотрите в режиме отладки, какой оператор вывода у вас будет использоваться, и сообщите всем нам. Договорились?


B>http://liveworkspace.org/code/fdd0855f606fd6ab597ddb408a370cb5


Сам объект типа класса не может быть преобразован к типу bool, если в классе нет соответствующей оператор-функции преобразования к типу bool. Это наглядно демонстрирует пример, которые я уже приводил ранее


int main()
{
   struct A {} a;
   if ( a );
}


Здесь условие в предложенит if требует преобразования выражения в тип bool, которое не происходит, так как в классе нет функции преобразования. Компилятор должен ивыдать сообщение об ошибке.

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

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

Теперь осталось разобраться, какой оператор вывода вызывается, либо для bool, либо для const void *.

Это зависит от того, во что преобразуется неявно указатель на функцию: либо в bool, либо в const void *.

Если он преобразуется в тип bool, то имеет место баг компилятора MS VC++.
Меня можно встретить на www.cpp.forum24.ru
Re[8]: Вывод лямбды
От: Сыроежка  
Дата: 16.08.12 12:25
Оценка:
Здравствуйте, const_volatile, Вы писали:

_>Здравствуйте, Сыроежка, Вы писали:


С>>
С>>#include <iostream>

С>>int f() { return 0; }

С>>int main()
С>>{
С>>   std::cout << f;
С>>}
С>>


С>>Посмотрите в режиме отладки, какой оператор вывода у вас будет использоваться, и сообщите всем нам. Договорились?


_>std::basic_ostream<char,struct std::char_traits<char> > & std::basic_ostream<char,struct std::char_traits<char> >::operator<<(bool)


Значит имеет место баг компилятора MS VC++.

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

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

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

Я исходил из положения стандарта, описанного в праграфе 2 раздела 4.10, в котором говорится, что

"2 A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The result of converting a “pointer to cv T” to a “pointer to cv void” points..."

Возможно я был не прав, и тут имеет место преобразваоние указателя к bool.
Меня можно встретить на www.cpp.forum24.ru
Re[9]: Вывод лямбды
От: Balthasar  
Дата: 16.08.12 12:33
Оценка:
"2 A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The result of converting a “pointer to cv T” to a “pointer to cv void” points..."

Может быть дело в том, что в нашем случае T не является object type?
Re[10]: Вывод лямбды
От: Masterkent  
Дата: 16.08.12 12:41
Оценка:
Balthasar:

B>"2 A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The result of converting a “pointer to cv T” to a “pointer to cv void” points..."


B>Может быть дело в том, что в нашем случае T не является object type?


Разумеется — см. 3.9/8:

An object type is a (possibly cv-qualified) type that is not a function type, not a reference type, and not a void type.


P.S.
VC++ 10 с отключенными расширениями (/Za) даёт правильный результат.
Re[11]: Вывод лямбды
От: Balthasar  
Дата: 16.08.12 12:47
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Balthasar:


B>>"2 A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The result of converting a “pointer to cv T” to a “pointer to cv void” points..."


B>>Может быть дело в том, что в нашем случае T не является object type?


M>Разумеется — см. 3.9/8:

M>

An object type is a (possibly cv-qualified) type that is not a function type, not a reference type, and not a void type.


M>P.S.

M>VC++ 10 с отключенными расширениями (/Za) даёт правильный результат.

Да я об этом и говорил, просто выразил в форме наводящего вопроса.
Re[12]: Вывод лямбды
От: uzhas Ниоткуда  
Дата: 16.08.12 12:49
Оценка:
Здравствуйте, Balthasar, Вы писали:

B>Да я об этом и говорил, просто выразил в форме наводящего вопроса.

ты слишком вежлив
так нельзя!
Re[10]: Вывод лямбды
От: Сыроежка  
Дата: 16.08.12 13:36
Оценка:
Здравствуйте, Balthasar, Вы писали:

B>"2 A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The result of converting a “pointer to cv T” to a “pointer to cv void” points..."


B>Может быть дело в том, что в нашем случае T не является object type?



Согласен. Но в любом случае вопрос связан с тем, может ли лямбда-выражение быть преобразовано к указателю на функцию, и уже затем лишь выбирается перегруженный оператор вывода для указателя на функцию. Если лямбда-выражение не имеет преобразования в указатель на функцию, как в случае, если она имеет не пустое capture, то будет ошибка компиляции.
Меня можно встретить на www.cpp.forum24.ru
Re[2]: Вывод лямбды
От: Erop Россия  
Дата: 16.08.12 13:39
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Поэтому значение, равное 1, для этого адреса — это особенность того компилятора, который вы используете. Другие компиляторы моогут выдать совершенно другое значение для адреса указателя на функцию для лямбда-выражения.


И что, ты правда веришь, что у ТС такой хитрый компилятор, в котором адрес кода может быть 1?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Вывод лямбды
От: Erop Россия  
Дата: 16.08.12 13:43
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Я вам советую проверить все те примеры кода, который я привел в своем сообщении, особенно тот пример, где имеет место явное преобразваоние лямбда объекта в указатель на функцию, а также пример, где имеется захватываемая переменная.


Ой, да ладно ужо-то...

Особенно рекомендую почитать предупрждениея компилятора:

source.cpp:9:17: warning: the address of 'void g()' will always evaluate as 'true' [-Waddress]

Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Вывод лямбды
От: Erop Россия  
Дата: 16.08.12 13:54
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Сам объект типа класса не может быть преобразован к типу bool, если в классе нет соответствующей оператор-функции преобразования к типу bool. Это наглядно демонстрирует пример, которые я уже приводил ранее


Тоже лажа!

С>
С>int main()
С>{
С>   struct A {} a;
С>   if ( a );
С>}
С>


Вот правильный пример. Попробуй найти там "оператор-функцию преобразования к типу bool. " (с)...


С>Это зависит от того, во что преобразуется неявно указатель на функцию: либо в bool, либо в const void *.

С>Если он преобразуется в тип bool, то имеет место баг компилятора MS VC++.

IMHO, в данном случае баг в твоём понимании стандарта. Указателди на функции к bool как раз могут, а к void* нет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[11]: Вывод лямбды
От: Сыроежка  
Дата: 16.08.12 15:38
Оценка: :)
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Сыроежка, Вы писали:


С>>Сам объект типа класса не может быть преобразован к типу bool, если в классе нет соответствующей оператор-функции преобразования к типу bool. Это наглядно демонстрирует пример, которые я уже приводил ранее


E>Тоже лажа!


С>>
С>>int main()
С>>{
С>>   struct A {} a;
С>>   if ( a );
С>>}
С>>


E>Вот правильный пример. Попробуй найти там "оператор-функцию преобразования к типу bool. " (с)...




У вас каша в голове. Вы просто не понимаете, что вы сами пишите в коде. В вашем примере не объект преобразуется к типу bool, а указатель на функцию преобразуется к типу bool. Указатель на функцию и объект класса — это разные понятия. Никакого преобразования объекта класса в тип bool в вашем примере нет.
Нет такого неявного преобразования из объекта класса в тип bool.

Так что ваш пример к не имеет отношения к преобразования объекта класса к типу bool и является совершенно некорректным в контексте этого преобразваония. Корректный пример я вам показал, который как раз и демонстрирует, что нет такого неявного преобразования из объекта класса в тип bool.
Меня можно встретить на www.cpp.forum24.ru
Re[12]: Вывод лямбды
От: Masterkent  
Дата: 16.08.12 16:29
Оценка:
Сыроежка:

E>>Вот правильный пример. Попробуй найти там "оператор-функцию преобразования к типу bool. " (с)...


С>У вас каша в голове. Вы просто не понимаете, что вы сами пишите в коде. В вашем примере не объект преобразуется к типу bool, а указатель на функцию преобразуется к типу bool. Указатель на функцию и объект класса — это разные понятия. Никакого преобразования объекта класса в тип bool в вашем примере нет.

С>Нет такого неявного преобразования из объекта класса в тип bool.

Это как раз у тебя каша в голове.

4/3:

An expression e can be implicitly converted to a type T if and only if the declaration T t=e; is well-formed, for some invented temporary variable t (8.5).

Выражение может быть преобразовано к некоему типу последовательностью преобразований, состоящей из более одного преобразования. Например, тут

#include <iostream>

struct Base {};
struct Derived : Base {};

typedef Derived Array[1];
Array array;

struct Source
{
    operator Array &() const { return array; }
};

int main()
{
    const Base *p = Source();
}

происходит сразу 4 неявных преобразования:

prvalue of type Source -> lvalue of type Derived[1] (user-defined conversion) -> prvalue of type Derived * (standard array-to-pointer conversion) -> Base * (standard pointer conversion) -> const Base * (standard qualification conversion).

И вполне можно сказать, что выражение Source() может быть преобразовано к const Base *.

О том, что в исходном примере лямбда преобразуется в bool ровно одним непосредственным преобразованием, тут никто не говорил.
Re[13]: Вывод лямбды
От: Сыроежка  
Дата: 16.08.12 16:37
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Сыроежка:


E>>>Вот правильный пример. Попробуй найти там "оператор-функцию преобразования к типу bool. " (с)...


С>>У вас каша в голове. Вы просто не понимаете, что вы сами пишите в коде. В вашем примере не объект преобразуется к типу bool, а указатель на функцию преобразуется к типу bool. Указатель на функцию и объект класса — это разные понятия. Никакого преобразования объекта класса в тип bool в вашем примере нет.

С>>Нет такого неявного преобразования из объекта класса в тип bool.

M>Это как раз у тебя каша в голове.


M>4/3:

M>

An expression e can be implicitly converted to a type T if and only if the declaration T t=e; is well-formed, for some invented temporary variable t (8.5).

M>Выражение может быть преобразовано к некоему типу последовательностью преобразований, состоящей из более одного преобразования. Например, тут

M>
#include <iostream>

M>struct Base {};
M>struct Derived : Base {};

M>typedef Derived Array[1];
M>Array array;

M>struct Source
M>{
M>    operator Array &() const { return array; }
M>};

M>int main()
M>{
M>    const Base *p = Source();
M>}

M>происходит сразу 4 неявных преобразования:

M>prvalue of type Source -> lvalue of type Derived[1] (user-defined conversion) -> prvalue of type Derived * (standard array-to-pointer conversion) -> Base * (standard pointer conversion) -> const Base * (standard qualification conversion).


M>И вполне можно сказать, что выражение Source() может быть преобразовано к const Base *.


M>О том, что в исходном примере лямбда преобразуется в bool ровно одним непосредственным преобразованием, тут никто не говорил.


Я говорил о том, что нет неявного стандартного преобразования объекта типа класса в тип bool, и продемонстрировал это конкретным примером, указав при этом, что нужна в классе оператор-функция преобразваония типов.
Так что не надо наводить тень на плетень. Вы сейчас дискуссируете сами с собой, так как ничего не опровергли. Во-первых, вы ничем не опровергли мой пример кода, демонстрирующий мое высказывание. Во-вторых, вы ввели функцию преобразваония в класс, о чем я с самого начала говорил..
Меня можно встретить на www.cpp.forum24.ru
Re[9]: Вывод лямбды
От: Roman Odaisky Украина  
Дата: 16.08.12 16:49
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Поэтому лучше смотреть на MS VC++ 2012.


А еще лучше на GCC. Выдает 1.
До последнего не верил в пирамиду Лебедева.
Re[5]: Вывод лямбды
От: zaufi Земля  
Дата: 16.08.12 16:56
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, Masterkent, Вы писали:


M>>В basic_ostream есть


U>виноват, ожидал лучшего от C++


а чего такого? это для того чтобы указатели печатать не запариваясь со всякими intptr_t и std::hex на каждый чих...
Re[14]: Вывод лямбды
От: Masterkent  
Дата: 16.08.12 17:45
Оценка:
Сыроежка:

С>Я говорил о том, что нет неявного стандартного преобразования объекта типа класса в тип bool


Цитирую:
Сам объект типа класса не может быть преобразован к типу bool, если в классе нет соответствующей оператор-функции преобразования к типу bool.

Здесь ни слова не сказано о том, что речь идёт конкретно про стандартные преобразования.

С>Вы сейчас дискуссируете сами с собой


Это ты намекаешь на свою невменяемость и бесполезность ведения дискуссий с тобой? Да я-то уже давно это понял, вот иногда и пытаюсь помочь другим это осознать.

По теме тут уже давно расписали что куда и в какой последовательности преобразуется.

С>Во-первых, вы ничем не опровергли мой пример кода, демонстрирующий мое высказывание.


Что означает "опровергнуть пример кода"? Что это за действие такое?

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


Давай-ка я напомню шибко башковитому парню, о чём он говорил с самого начала:

Сначала происходит преобразование объекта в указатель на функцию, а затем этот указатель на функцию преобразуется в тип void *, и для него вызывается оператор operator <<( const void * ).

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

U>выше уже отметили, что лямбда сконвертировалась в bool, и вызывался соответствующий operator<<(bool)

То, что вы раньше написали, совершеннно не корректно. С чего это, вдруг, лямбда объект должен преобразовываться к типу bool?!


Высказывание uzhas-а "лямбда сконвертировалась в bool" корректно: лямбда без lambda-capture может преобразовываться в bool двумя последовательными неявными преобразованиями, что и произошло в случае автора темы.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.