Почему std:: cout конвертируется в void * при использовании g++?
Почему можно нарисовать указатель std::ostream
на void
? Я не знаю какого-либо такого оператора преобразования в std::ostream
. Код ниже
#include <iostream>
int main()
{
void *p = std::cout; // why does this work?
}
Я задаю этот вопрос, так как я видел оператора размещения new
, вызываемого как
Foo* pFoo = new (std::cerr) Foo;
и понятия не имею, зачем писать такую вещь.
PS: Я компилирую с g++ 4.9.2 с или без -std=c++11
. clang++ не принимает код.
PSS: обнаружено, что из-за так называемой "безопасной проблемы bool" (см. ответ @nicebyte) в pre С++ 11 был определен оператор преобразования void*
для std::ostream
, который затем был удален в С++ 11. Тем не менее, мой код компилируется в С++ 11, используя g++. Более того, clang++ отвергает его независимо от того, какую версию стандарта я использую, даже с -std=c++98
, хотя я понимаю, что он должен принимать, если скомпилирован как pre-С++ 11.
Ответы
Ответ 1
Прочитайте это (на ваш вопрос ответили в самом последнем разделе "Безопасная проблема bool" ).
Чтобы выработать бит, реализация определяет неявное преобразование в void*
, определенное для таких вещей, как std::cin
и std::cout
, только для того, чтобы компилировать код, например while(std::cin>>x){...}
, тогда как код типа int x = std::cin;
не работает. Это все еще проблематично, потому что вы можете писать такие вещи, как в вашем примере.
С++ 11 решает эту проблему, введя явные преобразования.
Явный оператор преобразования выглядит так:
struct A {
explicit operator B() { ... } // explicit conversion to B
};
Когда A имеет явное преобразование в B, такой код становится законным:
A a;
B b(a);
Однако такой код не такой:
A a;
B b = a;
Конструкция типа if(std::cin)
требует, чтобы cin
преобразовывался в bool
, стандарт утверждает, что для того, чтобы преобразование было действительным в этом конкретном случае, код типа bool x(std::cin);
должен быть "законным". Это может быть достигнуто путем добавления явного преобразования в bool
. Это позволяет использовать cin/cout в вышеуказанном контексте, избегая при этом таких вещей, как int x = std::cout;
.
Для получения дополнительной информации см. страница Bjarne, а также этот вопрос.
Ответ 2
Отвечая на вопрос только о последующих действиях, поскольку ответ nicebyte идеально подходит для исходного вопроса.
Скорее всего, ваш gcc настроен на использование libstdС++ (который еще не изменил оператор из-за того, что он был изменением ABI), и ваш clang настроен на использование libС++ (который был с самого начала, стандартная библиотека С++ 11 и не совсем совместима в режиме С++ 98 - она предоставляет оператор преобразования bool, явный в С++ 11).
Ответ 3
Я думаю, что он допускает if (std::cout) ...
, не допуская неявного преобразования в bool
или что-то в этом роде.