Почему не вызывается лямбда мне понятно, не могу только никак понять, почему в stdout попадает именно 1. Или это implementation-defined в зависимости от того, как в компиляторе реализованы лямбды? Так, вроде как, лямбды в большинстве случаев представляются как объекты-функторы, а для применения к ним operator<< его ещё перегрузить надо. Или срабатывает преобразование к указателю void*? В общем, что говорит стандарт по данному поводу?
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>Почему не вызывается лямбда мне понятно, не могу только никак понять, почему в stdout попадает именно 1.
угу.. потому что ты ее не вызываешь, вот она и не вызывается
PMT>Почему данный код выводит именно 1?
PMT>http://liveworkspace.org/code/cb8b23a0336499531320c422d53999b0
PMT>Почему не вызывается лямбда мне понятно, не могу только никак понять, почему в stdout попадает именно 1. Или это implementation-defined в зависимости от того, как в компиляторе реализованы лямбды? Так, вроде как, лямбды в большинстве случаев представляются как объекты-функторы, а для применения к ним operator<< его ещё перегрузить надо. Или срабатывает преобразование к указателю void*? В общем, что говорит стандарт по данному поводу?
Сначала происходит преобразование объекта в указатель на функцию, а затем этот указатель на функцию преобразуется в тип void *, и для него вызывается оператор operator <<( const void * ).
Если вы измените ваш пример, добавив захватываемую переменную, то код уже не должен компилироваться, так как для лямбда-выражений, имеющих захватываемые переменные, оператор-функция преобразования в указатель на функцию не создается. Рассмотрите следующий код
#include <iostream>
int main()
{
int x = 0;
auto lm = [x] { return x; };
std::cout << lm << std::endl;
}
Компилятор для этого кода должен сгенерировать ошибку компиляции, так как для объекта lm, который представляет собой объект лямбда-выражения, не определен оператор operator <<.
С другой стороны, вы можете скомпилировать следующий код
Этот код даст тот же самый результат, который вы получили для своего собственного исходного примера. Только в моем примере я явно преобразую лямбда-выражение в указатель на функцию.
Поэтому значение, равное 1, для этого адреса — это особенность того компилятора, который вы используете. Другие компиляторы моогут выдать совершенно другое значение для адреса указателя на функцию для лямбда-выражения.
Здравствуйте, Сыроежка, Вы писали:
С>Сначала происходит преобразование объекта в указатель на функцию, а затем этот указатель на функцию преобразуется в тип void *, и для него вызывается оператор operator <<( const void * ).
1) указатель на функцию нельзя неявно скастить к void*, пример: http://liveworkspace.org/code/c3ed22b220ef3a2e3a73cb9282be7376
2) operator<<(void*) не существует, в C++ стараются работать с конкретными типами, избегая void*
выше уже отметили, что лямбда сконвертировалась в bool, и вызывался соответствующий operator<<(bool)
С>Поэтому значение, равное 1, для этого адреса — это особенность того компилятора, который вы используете.
адрес 1 должен был вам намекнуть, что вы думаете в неправильном направлении
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, Сыроежка, Вы писали:
С>>Сначала происходит преобразование объекта в указатель на функцию, а затем этот указатель на функцию преобразуется в тип void *, и для него вызывается оператор operator <<( const void * ). U>1) указатель на функцию нельзя неявно скастить к void*, пример: http://liveworkspace.org/code/c3ed22b220ef3a2e3a73cb9282be7376 U>2) operator<<(void*) не существует, в C++ стараются работать с конкретными типами, избегая void*
Во-первых, у меня было написано не operator <<( void * ), а operator <<( const void * ).
Вы можете расширить свои знания по С++, узнав, что в стандарте С++ имеется следующий оператор
basic_ostream<charT,traits>& operator<<(const void* p);
U>выше уже отметили, что лямбда сконвертировалась в bool, и вызывался соответствующий operator<<(bool)
То, что вы раньше написали, совершеннно не корректно. С чего это, вдруг, лямбда объект должен преобразовываться к типу bool?!
С>>Поэтому значение, равное 1, для этого адреса — это особенность того компилятора, который вы используете. U>адрес 1 должен был вам намекнуть, что вы думаете в неправильном направлении
Я вам советую проверить все те примеры кода, который я привел в своем сообщении, особенно тот пример, где имеет место явное преобразваоние лямбда объекта в указатель на функцию, а также пример, где имеется захватываемая переменная.
Идите вместе с uzhas учить С++ и не позорьтесь, ставя -1 совершенно корректному ответу. Лучше будет, если вы сначала будете думать, а уж потом тянуть свои ручонки ставить -1 правильным ответам.
M>>но тут оно, конечно же, не при делах.
С>Идите вместе с uzhas учить С++ и не позорьтесь, ставя -1 совершенно корректному ответу.
ответ некорректный, поскольку operator<<(ostream&, const void*) в выводе указателя не функцию (к которому преобразуется лямбда) не участвует. а то, что выводится "1" (при std::boolalpha "true") означает, что имеет место Boolean conversion:
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool.
лямбда преобразуется к указателю согласно разделу Function-to-pointer conversion
An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to the function.
согласно разделу Pointer conversions, в cv-void* может быть сконвертирован только указатель на объект:
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 C++ object model, функции объектами не являются:
An object is a region of storage. [ Note: A function is not an object, regardless of whether or not it occupies storage in the way that objects do. —end note ]
таким образом, резюмируя вышесказанное, лямбда преобразуется к типу "указатель на функцию", который преобразуется к типу bool, после чего вызывается operator<<(ostream&, bool).
M>>>но тут оно, конечно же, не при делах.
С>>Идите вместе с uzhas учить С++ и не позорьтесь, ставя -1 совершенно корректному ответу.
_>ответ некорректный, поскольку operator<<(ostream&, const void*) в выводе указателя не функцию (к которому преобразуется лямбда) не участвует. а то, что выводится "1" (при std::boolalpha "true") означает, что имеет место Boolean conversion:
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool.
_>лямбда преобразуется к указателю согласно разделу Function-to-pointer conversion
An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to the function.
_>согласно разделу Pointer conversions, в cv-void* может быть сконвертирован только указатель на объект:
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 C++ object model, функции объектами не являются:
An object is a region of storage. [ Note: A function is not an object, regardless of whether or not it occupies storage in the way that objects do. —end note ]
_>таким образом, резюмируя вышесказанное, лямбда преобразуется к типу "указатель на функцию", который преобразуется к типу bool, после чего вызывается operator<<(ostream&, bool).
Выполните, пожалуйста, сначала очень простой код
#include <iostream>
int f() { return 0; }
int main()
{
std::cout << f;
}
Посмотрите в режиме отладки, какой оператор вывода у вас будет использоваться, и сообщите всем нам. Договорились?
Я же пока замечу, что чтобы объект типа класса был преобразован к типу bool, в этом классе должна быть определена оператор-функция преобразования типов. Если такой функции в классе нет, то никакого преобразования к bool не будет.
const_volatile:
_>лямбда преобразуется к указателю согласно разделу Function-to-pointer conversion
An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to the function.
Там не function-to-pointer conversion, а user-defined conversion performed by conversion function. Лямбда — это не функция, а closure object классового типа. И тут применяются следующие правила:
8.5/16:
The semantics of initializers are as follows. The destination type is the type of the object or reference being initialized and the source type is the type of the initializer expression. If the initializer is not a single (possibly parenthesized) expression, the source type is not defined.
— If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized (8.5.4).
— If the destination type is a reference type, see 8.5.3.
— If the destination type is an array of characters, an array of char16_t, an array of char32_t, or an array of wchar_t, and the initializer is a string literal, see 8.5.2.
— If the initializer is (), the object is value-initialized.
— Otherwise, if the destination type is an array, the program is ill-formed.
— If the destination type is a (possibly cv-qualified) class type:
[...] — Otherwise, if the source type is a (possibly cv-qualified) class type, conversion functions are considered. The applicable conversion functions are enumerated (13.3.1.5), and the best one is chosen through overload resolution (13.3). The user-defined conversion so selected is called to convert the initializer expression into the object being initialized. If the conversion cannot be done or is ambiguous, the initialization is ill-formed.[/b]
[...]
13.3.1.5:
Under the conditions specified in 8.5, as part of an initialization of an object of nonclass type, a conversion function can be invoked to convert an initializer expression of class type to the type of the object being initialized. Overload resolution is used to select the conversion function to be invoked. Assuming that “cv1 T” is the type of the object being initialized, and “cv S” is the type of the initializer expression, with S a class type, the candidate functions are selected as follows:
— The conversion functions of S and its base classes are considered. Those non-explicit conversion functions that are not hidden within S and yield type T or a type that can be converted to type T via a standard conversion sequence (13.3.3.1.1) are candidate functions. For direct-initialization, those explicit conversion functions that are not hidden within S and yield type T or a type that can be converted to type T with a qualification conversion (4.4) are also candidate functions. Conversion functions that return a cv-qualified type are considered to yield the cv-unqualified version of that type for this process of selecting candidate functions. Conversion functions that return “reference to cv2 X” return lvalues or xvalues, depending on the type of reference, of type “cv2 X” and are therefore considered to yield X for this process of selecting candidate functions.
Результат вызова conversion function — указатель на функцию, он неявно преобразуется в bool.
С>Этот код даст тот же самый результат, который вы получили для своего собственного исходного примера. Только в моем примере я явно преобразую лямбда-выражение в указатель на функцию.
С>Поэтому значение, равное 1, для этого адреса — это особенность того компилятора, который вы используете. Другие компиляторы моогут выдать совершенно другое значение для адреса указателя на функцию для лямбда-выражения.
Compilation output:
source.cpp: In function 'int main()':
source.cpp:7:81: warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object [enabled by default]
Execution output:
true
0x8048b16
Так что там про адрес со значением 1 и особенности компилятора?
Здравствуйте, Сыроежка, Вы писали:
С>Посмотрите в режиме отладки, какой оператор вывода у вас будет использоваться, и сообщите всем нам. Договорились?
провел тест на VS2010, действительно, вызывается operator<<(const void *_Val), при этом печатается адрес функции 00E340C6
похоже на баг
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, Сыроежка, Вы писали:
С>>Посмотрите в режиме отладки, какой оператор вывода у вас будет использоваться, и сообщите всем нам. Договорились? U>провел тест на VS2010, действительно, вызывается operator<<(const void *_Val), при этом печатается адрес функции 00E340C6 U>похоже на баг
Я думаю, что надо смотреть MS VC++ 2012 RC. Дело в том, что в MS VC++ 2010 имеются серьезные недаработки в реализации лямбда-выражений. С одной стороны, нельзя явно преобразовать лямбда-выражение в указатель на функцию. С другой стороны, в своей библиотеке MS этим преобразованием пользуется.
M>>>>но тут оно, конечно же, не при делах.
С>>>Идите вместе с uzhas учить С++ и не позорьтесь, ставя -1 совершенно корректному ответу.
_>>ответ некорректный, поскольку operator<<(ostream&, const void*) в выводе указателя не функцию (к которому преобразуется лямбда) не участвует. а то, что выводится "1" (при std::boolalpha "true") означает, что имеет место Boolean conversion:
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool.
_>>лямбда преобразуется к указателю согласно разделу Function-to-pointer conversion
An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to the function.
_>>согласно разделу Pointer conversions, в cv-void* может быть сконвертирован только указатель на объект:
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 C++ object model, функции объектами не являются:
An object is a region of storage. [ Note: A function is not an object, regardless of whether or not it occupies storage in the way that objects do. —end note ]
_>>таким образом, резюмируя вышесказанное, лямбда преобразуется к типу "указатель на функцию", который преобразуется к типу bool, после чего вызывается operator<<(ostream&, bool).
С>Выполните, пожалуйста, сначала очень простой код
С>Посмотрите в режиме отладки, какой оператор вывода у вас будет использоваться, и сообщите всем нам. Договорились?
С>Я же пока замечу, что чтобы объект типа класса был преобразован к типу bool, в этом классе должна быть определена оператор-функция преобразования типов. Если такой функции в классе нет, то никакого преобразования к bool не будет.
Сам объект типа класса не может быть преобразован к типу bool, если в классе нет соответствующей оператор-функции преобразования к типу bool. Это наглядно демонстрирует пример, которые я уже приводил ранее
int main()
{
struct A {} a;
if ( a );
}
Здесь условие в предложенит if требует преобразования выражения в тип bool, которое не происходит, так как в классе нет функции преобразования. Компилятор должен ивыдать сообщение об ошибке.
Поэтому, возвращаясь к исходному примеру темы, в любом случае сначала происходит преобразование лямбда-выражения в указатель на функцию. Я уже приводил другой пример, когда если для лямбда-выражения такой опреатор-функции не существует по причине, что лямбда-выражение захватывает локальную переменную, то код вообще не будет компилироваться.
Следовательно очевидно, что происходит преобразование в указатель на функцию для лямбда-выражения.
Теперь осталось разобраться, какой оператор вывода вызывается, либо для bool, либо для const void *.
Это зависит от того, во что преобразуется неявно указатель на функцию: либо в bool, либо в const void *.
Если он преобразуется в тип bool, то имеет место баг компилятора MS VC++.
С>>Посмотрите в режиме отладки, какой оператор вывода у вас будет использоваться, и сообщите всем нам. Договорились?
_>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.
"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?
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) даёт правильный результат.
Здравствуйте, 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) даёт правильный результат.
Да я об этом и говорил, просто выразил в форме наводящего вопроса.
Здравствуйте, 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, то будет ошибка компиляции.
Здравствуйте, Сыроежка, Вы писали:
С>Поэтому значение, равное 1, для этого адреса — это особенность того компилятора, который вы используете. Другие компиляторы моогут выдать совершенно другое значение для адреса указателя на функцию для лямбда-выражения.
И что, ты правда веришь, что у ТС такой хитрый компилятор, в котором адрес кода может быть 1?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Сыроежка, Вы писали:
С>Я вам советую проверить все те примеры кода, который я привел в своем сообщении, особенно тот пример, где имеет место явное преобразваоние лямбда объекта в указатель на функцию, а также пример, где имеется захватываемая переменная.
Особенно рекомендую почитать предупрждениея компилятора:
source.cpp:9:17: warning: the address of 'void g()' will always evaluate as 'true' [-Waddress]
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Сыроежка, Вы писали:
С>Сам объект типа класса не может быть преобразован к типу bool, если в классе нет соответствующей оператор-функции преобразования к типу bool. Это наглядно демонстрирует пример, которые я уже приводил ранее
Тоже лажа!
С>
С>int main()
С>{
С> struct A {} a;
С> if ( a );
С>}
С>
Вот правильный пример. Попробуй найти там "оператор-функцию преобразования к типу bool. " (с)...
С>Это зависит от того, во что преобразуется неявно указатель на функцию: либо в bool, либо в const void *. С>Если он преобразуется в тип bool, то имеет место баг компилятора MS VC++.
IMHO, в данном случае баг в твоём понимании стандарта. Указателди на функции к bool как раз могут, а к void* нет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Сыроежка, Вы писали:
С>>Сам объект типа класса не может быть преобразован к типу bool, если в классе нет соответствующей оператор-функции преобразования к типу bool. Это наглядно демонстрирует пример, которые я уже приводил ранее
E>Тоже лажа!
С>>
С>>int main()
С>>{
С>> struct A {} a;
С>> if ( a );
С>>}
С>>
E>Вот правильный пример. Попробуй найти там "оператор-функцию преобразования к типу bool. " (с)...
У вас каша в голове. Вы просто не понимаете, что вы сами пишите в коде. В вашем примере не объект преобразуется к типу bool, а указатель на функцию преобразуется к типу bool. Указатель на функцию и объект класса — это разные понятия. Никакого преобразования объекта класса в тип bool в вашем примере нет.
Нет такого неявного преобразования из объекта класса в тип bool.
Так что ваш пример к не имеет отношения к преобразования объекта класса к типу bool и является совершенно некорректным в контексте этого преобразваония. Корректный пример я вам показал, который как раз и демонстрирует, что нет такого неявного преобразования из объекта класса в тип bool.
Сыроежка:
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 ровно одним непосредственным преобразованием, тут никто не говорил.
Здравствуйте, 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>
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, и продемонстрировал это конкретным примером, указав при этом, что нужна в классе оператор-функция преобразваония типов.
Так что не надо наводить тень на плетень. Вы сейчас дискуссируете сами с собой, так как ничего не опровергли. Во-первых, вы ничем не опровергли мой пример кода, демонстрирующий мое высказывание. Во-вторых, вы ввели функцию преобразваония в класс, о чем я с самого начала говорил..
Сыроежка:
С>Я говорил о том, что нет неявного стандартного преобразования объекта типа класса в тип bool
Цитирую: Сам объект типа класса не может быть преобразован к типу bool, если в классе нет соответствующей оператор-функции преобразования к типу bool.
Здесь ни слова не сказано о том, что речь идёт конкретно про стандартные преобразования.
С>Вы сейчас дискуссируете сами с собой
Это ты намекаешь на свою невменяемость и бесполезность ведения дискуссий с тобой? Да я-то уже давно это понял, вот иногда и пытаюсь помочь другим это осознать.
По теме тут уже давно расписали что куда и в какой последовательности преобразуется.
С>Во-первых, вы ничем не опровергли мой пример кода, демонстрирующий мое высказывание.
Что означает "опровергнуть пример кода"? Что это за действие такое?
С>Во-вторых, вы ввели функцию преобразваония в класс, о чем я с самого начала говорил..
Давай-ка я напомню шибко башковитому парню, о чём он говорил с самого начала:
Сначала происходит преобразование объекта в указатель на функцию, а затем этот указатель на функцию преобразуется в тип void *, и для него вызывается оператор operator <<( const void * ).
О том, что подобная фигня имеет место лишь применительно к конкретно взятому компилятору с конкретными настройками (нестандартные расширения включены) и что такое поведение не является соответствующим стандарту, автор процитированного, видимо, не знал, не так ли?
U>выше уже отметили, что лямбда сконвертировалась в bool, и вызывался соответствующий operator<<(bool)
То, что вы раньше написали, совершеннно не корректно. С чего это, вдруг, лямбда объект должен преобразовываться к типу bool?!
Высказывание uzhas-а "лямбда сконвертировалась в bool" корректно: лямбда без lambda-capture может преобразовываться в bool двумя последовательными неявными преобразованиями, что и произошло в случае автора темы.