Подтвердить что ты не робот

Почему 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.

4b9b3361

Ответ 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 или что-то в этом роде.