Проблема заключается в том, что количество пользовательских преобразований, которые вызываются неявно, ограничено (до 1) стандартом.
B ob = a;
подразумевает два пользовательских преобразования:
- на
a
: Wrap<A>::operator A*()
следует называть
- на результат:
B::B(A*)
должен называться
@ Объяснение Джеймса Канзе: этот синтаксис называется "инициализацией копирования", фактически эквивалентным B ob = B(a)
(при этом копия в большинстве случаев исключается). Это отличается от B ob(a)
, который является «прямой инициализацией» и сработал бы.
если вы явно укажете что-либо из этого, оно будет работать, например:
B ob = B(a);
С другой стороны, для второго случая нет проблем:
ob = a;
сокращенно для:
ob.operator=(a);
И поэтому требуется только одно пользовательское преобразование, которое разрешено.
EDIT
Поскольку это было необходимо в комментарии (к ответу Кирилла), мы можем предположить мотив.
Цепные преобразования могут быть длинными, очень длинными, и поэтому:
- может удивить пользователей - неявные преобразования могут уже удивлять, как это ...
- может привести к экспоненциальному поиску возможностей (для компилятора) - он должен идти с обоих концов, пытаясь проверить все возможные преобразования и как-то "соединить" их (с кратчайшим возможным путем).
Кроме того, до тех пор, пока существует более 1 преобразования, вы рискуете иметь циклы, которые необходимо будет обнаружить (даже если диагностика, вероятно, не потребуется и будет зависеть от качества выполнения).
Таким образом, поскольку лимит необходим для того, чтобы избежать бесконечно долгих поисков (его можно было бы оставить неопределенным, с минимальным необходимым), и поскольку после 1 у нас могут возникнуть новые проблемы (циклы), то 1 кажется таким же хорошим пределом любой в конце концов.