Каково обоснование, чтобы не допускать перегрузки оператора преобразований C ++ с помощью функций, не являющихся членами - PullRequest
5 голосов
/ 29 апреля 2010

C ++ 0x добавил явные операторы преобразования, но они всегда должны быть определены как члены класса Source. То же самое относится к оператору присваивания, оно должно быть определено в классе Target.

Когда классы Source и Target необходимого преобразования не зависят друг от друга, ни Source не может определить оператор преобразования, ни Target не может определить конструктор из Source.

Обычно мы получаем это, определяя определенную функцию, такую ​​как

Target ConvertToTarget(Source& v);

Если бы C ++ 0x позволял перегружать оператор преобразования не функциями-членами, мы могли бы, например, определить явное или неявное преобразование между несвязанными типами.

template < typename To, typename From >
operator To(const From& val);

Например, мы могли бы специализировать преобразование из chrono :: time_point в posix_time :: ptime следующим образом

template < class Clock, class Duration>
operator boost::posix_time::ptime(
const boost::chrono::time_point<Clock, Duration>& from)
{
  using namespace boost;
  typedef chrono::time_point<Clock, Duration> time_point_t;
  typedef chrono::nanoseconds duration_t;
  typedef duration_t::rep rep_t;
  rep_t d = chrono::duration_cast<duration_t>(
  from.time_since_epoch()).count();
  rep_t sec = d/1000000000;
  rep_t nsec = d%1000000000;
  return  posix_time::from_time_t(0)+
    posix_time::seconds(static_cast<long>(sec))+
    posix_time::nanoseconds(nsec);
}

И использовать преобразование как любое другое преобразование.

Для более полного описания проблемы см. здесь или в моей Boost.Conversion библиотеке ..

Таким образом, вопрос заключается в следующем: каково обоснование того, чтобы запретить перегрузку оператора преобразований C ++ с функциями, не являющимися членами?

Ответы [ 2 ]

5 голосов
/ 29 апреля 2010

С текущими правилами, чтобы определить, можете ли вы конвертировать между двумя классами, вам нужно смотреть только в двух местах: в определениях источника и цели. Если бы вы могли определить преобразования как функции, не являющиеся членами, функция преобразования могла бы быть где угодно, что могло бы значительно затруднить нахождение причины нежелательных или неоднозначных преобразований (в дополнение к тому, что компилятору приходится работать сложнее, чтобы найти возможное преобразование во всех случаях, когда преобразование было необходимо или возможно, например, перегрузка оператора).

Не думаю, что предложенный вами шаблон будет очень практичным. Хотя вы могли бы явно специализировать его для преобразования, если у вас был соответствующий особый случай, он все равно перехватывал бы все другие преобразования, вызывая неоднозначности с любыми ранее существовавшими преобразованиями.

Это, возможно, два потенциальных фактора, не позволяющих такое преобразование.

1 голос
/ 29 апреля 2010

Если между Source и Destination нет прямой связи, то я хочу явно идентифицировать преобразования между ними, как с функцией Source sourceFromDestination(const Destination&), и не удивляться случайным неявным преобразованиям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...