Перегруженная функция с nullptr не вызывается

У меня есть следующее:

void func(const char *p) { std::cout << p << "\n"; }
void func(std::nullptr_t p) { std::cout << "<null>\n"; }

int main()
{
    func("test");
    char *p=nullptr;
    func(p);
    func(nullptr);
    return 0;
}

func("test") всегда вызывается. С комментарием func(p) вызывается func(nullptr), но когда func(p) не комментируется, ни один из них не вызывается. Почему бы и нет? Почему func(p) с p==nullptr вызывает не func(nullptr), а вместо этого вызывает func(const char*)?

[edit]
Основываясь на ответах, я пришел к выводу, что func(...) вызывается на основе типа параметра, а p имеет тип char*, установка значения p на nullptr не меняет тип и не будет измените, что вызывается func (char *) - как также объясняет принятый ответ.


person slashmais    schedule 09.06.2014    source источник
comment
Связано: stackoverflow.com/questions /23283772/   -  person 0x499602D2    schedule 09.06.2014
comment
Можете ли вы изменить его, чтобы не пытаться использовать нулевой указатель func(p) использует нулевой указатель, который является неопределенным поведением. Что происходит, когда вы делаете это изменение? См. ideone.com/gSNG6m.   -  person Dave S    schedule 09.06.2014
comment
@DaveS: не знаю, понимаю ли я, что вы имеете в виду, но если p указывает на действительную c-строку, все работает нормально.   -  person slashmais    schedule 09.06.2014
comment
@slashmais Потому что, если вы собираетесь печатать нулевой указатель, это устанавливает бит в маске ошибок потока. Когда это произойдет, вы больше не сможете выполнять вывод, если снова не очистите маску ошибки.   -  person 0x499602D2    schedule 09.06.2014
comment
@ 0x499602D2: да, я видел это в связанном вопросе, и это причина. Я отредактировал свой вопрос: почему func (nullptr) не вызывается с p == nullptr? аааа - хорошо, теперь я вижу: функции вызываются на основе типа, и в этом случае nullptr - это значение, присвоенное p, и оно не меняет тип p.   -  person slashmais    schedule 09.06.2014
comment
@slashmais Это правильно. Компилятор должен решить, какую версию func вызывать во время компиляции, поэтому невозможно, чтобы это основывалось на текущем значении переменной-аргумента — только на ее статическом типе.   -  person dlf    schedule 09.06.2014
comment
@dlf: да, и единственный случай, когда он будет работать по значению, я думаю, с вариативными шаблонами - теперь нужно проверить эту идею;)   -  person slashmais    schedule 09.06.2014
comment
Пожалуйста, обновите свой вопрос, так как он больше не является внутренне согласованным. Вы получите результат от всех трех вызовов функций во всех случаях; вопрос в том, какой вывод. Обновите его, перефразировав и очистив, а не добавляя еще одну правку: отрывки без знаков препинания или заглавных букв.   -  person Lightness Races in Orbit    schedule 09.06.2014


Ответы (1)


Точное содержание вашего вопроса на самом деле глубоко запутано, потому что причина, по которой вы видели, что вещи «не вызываются», заключалась в том, что ваш исходный код пытался передать указатель нулевого символа, который устанавливает флаг ошибки в потоке и не позволяет ему работать снова, пока он не будет исправлен. В любом случае, вот суть ответа:


Вы не можете присвоить nullptr char* и ожидать, что char* волшебным образом превратится в std::nullptr_t. Ваш указатель по-прежнему char*, и он имеет значение nullptr.

Преимущество std::nullptr_t заключается в том, что литерал нулевого указателя имеет собственный отдельный тип, который не преобразуется в целые типы; это не означает, что вы можете ожидать использования типа std::nullptr_t везде, где указатель имеет значение 0.

person Lightness Races in Orbit    schedule 09.06.2014
comment
Да, я пришел к такому выводу. Жаль, что это не так, если бы это было возможно, то многие проблемы решились бы... :) - person slashmais; 09.06.2014
comment
@slashmais C ++ имеет статическую систему типов, вы не можете использовать ее, чтобы узнать о свойствах времени выполнения. - person Alan Stokes; 10.06.2014
comment
@AlanStokes: Ну, это не совсем статично, и да, вы можете. Только не этот. - person Lightness Races in Orbit; 10.06.2014