Ответ 1
Это также относится к g++
4.8.4 со следующим:
g++ -g -pedantic --std=c++11 -o test main.cpp
Все настройки VS2015 установлены по умолчанию.
Проблема заключается в том, что компилятор пытается преобразовать временный объект, возвращенный ConvertsToPtr()
в объект shared_ptr
. Когда компилятор используется с ключевым словом explicit
, это преобразование никогда не происходит с помощью конструктора. Однако при рассмотрении с помощью gdb
появляется, что вместо этого используется функция преобразования shared_ptr<A> const &()
для соответствия соответствующему типу. Затем это преобразование возвращает a const shared_ptr &
, который не имеет двусмысленности при вызове оператора присваивания (это также соответствует выводам wojciech Frohmberg).
Однако, если explicit
опущен, возвращается объект shared_ptr
. это может быть сопоставлено либо с rvalue версией оператора присваивания, либо с версией const lvalue.
Согласно N4296, Table-11, то после построения с объектом conversion constructor
a rvalue of shared_ptr
, Однако разрешение перегрузки обнаруживает два совпадения, оба из которых находятся под Exact Match
(версия rvalue Identity matching
, а другая находится под Qualification matching
).
Я также проверял также на VS2015
и, как указано в комментариях, работает. Но, используя некоторую отладку cout
, можно увидеть, что значение const lvalue присваивание имеет приоритет по сравнению с версией relalence rvalue const lvalue.
EDIT: Я посмотрел немного глубже в стандарте и добавил модификацию. удаленный текст относительно результатов VS2015
был неправильным, потому что я не определял оба назначения. Когда оба назначения были объявлены, он предпочитает rvalue.
Я предполагаю, что компилятор VS отличает Identity
от соответствия Qualification
в ранжировании. Однако, как я заключаю, это компилятор VS не работает. компиляторы g++
подчиняются данному стандарту. Однако, поскольку GCC 5.0 работает как Visual Studio, возможность ошибки компилятора является тонкой, поэтому я был бы рад увидеть другие мнения экспертов.
РЕДАКТИРОВАТЬ: В 13.3.3.2 один из механизмов прерывания, после лучшего рейтинга, о котором я писал, есть:
- S1 и S2 являются ссылочными привязками (8.5.3), и ни одна из них не относится к неявный параметр объекта объявленной нестатической функции-члена без ref-qualifier, а S1 связывает ссылку rvalue с rvalue и S2 связывает ссылку lvalue.
Приведен пример, показывающий, что заданное значение rvalue (не rvalue reference) должно соответствовать const int &&
over const int &
. Поэтому, я думаю, можно с уверенностью предположить, что это имеет отношение к нашему случаю, даже если у нас есть тип &&
, а не тип const &&
. Думаю, после всего, что GCC
4.7,4.8 все-таки глючит.