Это также случай с g++
4.8.4 со следующим:
g++ -g -pedantic --std=c++11 -o test main.cpp
Установки VS2015 все по умолчанию.
Проблема заключается в том, что компилятор пытается преобразовать временный объект, возвращенный ConvertsToPtr()
в объект shared_ptr
. Когда компилятор используется с ключевым словом explicit
, это преобразование никогда не происходит с помощью конструктора. Однако при рассмотрении с помощью gdb
появляется, что вместо этого используется функция преобразования shared_ptr<A> const &()
для соответствия соответствующему типу. Затем это преобразование возвращает const shared_ptr &
, который не имеет двусмысленности при вызове оператора присваивания (это также соответствует выводам wojciech Frohmberg).
Однако, если explicit
опущен, возвращается объект shared_ptr
. это может быть сопоставлено либо с rvalue версией оператора присваивания, либо с версией const lvalue.
Согласно N4296, Table-11, мы имеем после строительства с conversion constructor
объект rvalue of shared_ptr
. Однако разрешение перегрузки обнаруживает два совпадения, оба из которых находятся под Exact Match
(версия rvalue равна Identity matching
, а другая - Qualification matching
).
Я также проверял также на VS2015
и, как указано в комментариях, он работает. Но, используя некоторую отладку cout
, можно видеть, что назначение const lvalue имеет приоритет над значением rvalue const lvalue refrence version.
EDIT: Я посмотрел немного глубже в стандарте и добавил модификацию. удаленный текст относительно результатов VS2015
был неправильным, потому что я не определял оба назначения. Когда оба назначения были объявлены, он предпочитает rvalue.
Я предполагаю, что VS-компилятор отличает Identity
от Qualification
, соответствующих ранжированию. Однако, как я заключаю, это компилятор VS не работает. компиляторы g++
подчиняются данному стандарту. Однако, поскольку GCC 5.0 работает как Visual Studio, возможность ошибки компилятора тонкая, поэтому я был бы рад увидеть других экспертов.
EDIT: В 13.3.3.2 один из вытяжных выключателей, после лучшего ранжирования я писал об этом, это:
— S1 and S2 are reference bindings (8.5.3) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference.
Существует пример прилагается, показывающими, что данный Rvalue (не Rvalue ссылки) должен совпадать с const int &&
над const int &
. Поэтому, я думаю, можно с уверенностью предположить, что это относится к нашему делу, даже если у нас есть тип &&
, а не тип const &&
. Я думаю, после всего этого GCC
4.7.4.8 в любом случае глючит.
Принято GCC 5+, отклонено 4.9 и Clang. –
Что касается этой ошибки: I * think * две возможности - это либо конструктор 'const shared_ptr &' из результата функции преобразования 'ConvertsToPtr', и' shared_ptr && 'конструктор из временного' shared_ptr ', который построен из' Args = {ConvertsToPtr} '. Но я не уверен, что они должны быть одинаково хорошими. –
@Alf meh. my_namespace :: shared_ptr и std :: shared_ptr - разные имена. – AndyJost