Ответ 1
После того, как я удалю оператор unsigned long int, зачем мне явно указывать x на std::string? Почему он не вызывает неявный оператор литья (std::string) напрямую?
Версия <<
для строк - это шаблон, параметризованный параметрами шаблона std::basic_string
(std::string
сам по себе является специализацией этого шаблона). Его можно выбрать только с помощью зависящего от аргумента поиска, и это работает только в том случае, если аргумент фактически является специализацией std::basic_string
, а не чем-то, конвертируемым в это.
Есть ли какая-либо документация, которая объясняет, какие неявные броски разрешены и каков их порядок приоритета?
Правила довольно сложны, и вам нужно будет прочитать стандарт С++ для полной истории. Простые эмпирические правила заключаются в том, что неявные преобразования не могут содержать более одного пользовательского преобразования и (как вы выяснили), результат неявного преобразования не может использоваться для выбора специализации шаблона с помощью зависящего от аргумента поиска.
Я не уверен, что полностью понимаю связанные с этим предостережения. Может кто-нибудь, пожалуйста, набросайте их?
Я не совсем понимаю их; взаимодействия между неявными преобразованиями, поиск имени и специализация шаблонов (и, возможно, другие факторы, о которых я не могу сейчас думать) довольно сложны, и большинство людей не склонны изучать их все. Существует довольно много примеров, когда неявное преобразование не будет происходить, и другие, где это может произойти, когда вы этого не ожидаете; лично мне легче просто избегать неявных преобразований большую часть времени.
Лучше ли было бы просто определять общедоступные методы ToUnsignedLongInt и ToString?
Это, вероятно, хорошая идея, чтобы избежать нежелательных преобразований. Вы можете исправить свою проблему, оставив их и используя их явно при необходимости:
std::cout << std::string(x) << std::endl;
В С++ 11 вы можете объявить их explicit
, чтобы их можно было использовать только таким образом. На мой взгляд, это был бы лучший вариант, если можно; в противном случае я бы использовал явные функции преобразования, которые вы предлагаете.
Кстати, возвращаемый тип main()
должен быть int
, а не void
.