views:

185

answers:

2

C++0x has added explicit conversion operators, but they must always be defined as members of the Source class. The same applies to the assignment operator, it must be defined on the Target class.

When the Source and Target classes of the needed conversion are independent of each other, neither the Source can define a conversion operator, neither the Target can define a constructor from a Source.

Usually we get it by defining a specific function such as

Target ConvertToTarget(Source& v);

If C++0x allowed to overload conversion operator by non member functions we could for example define the conversion implicitly or explicitly between unrelated types.

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

For example we could specialize the conversion from chrono::time_point to posix_time::ptime as follows

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);
}

And use the conversion as any other conversion.

For a more complete description of the problem, see here or on my Boost.Conversion library..

So the question is: What is the rationale to non allow overloading of C++ conversions operator with non-member functions?

+4  A: 

With the current rules, to work out whether you can convert between two classes you only need to look in two places: the source and target definitions. If you could define conversions as non-member functions the conversion function could be anywhere which might make finding the cause of unwanted or ambiguous conversions much more difficult (in addition to making the compiler work harder to find possible conversion in all cases where a conversion was need or possible e.g. operator overloading).

I don't think that your proposed template would be very practical. Although you could explicitly specialize it for conversion where you did have an appropriate special case, it would still catch all other conversions causing ambiguities with any pre-existing conversions.

These are perhaps two potential factors in not allowing such conversion.

Charles Bailey
I don't think that this could be harder for the compiler.
Vicente Botet Escriba
The problem of locality is inherent to any non-member function that can be specialized or overloaded for specific types. This don't preclude C++ to have non-member functions. For example we can have a generic convert_to function (see http://viboes.blogspot.com/2010/04/extrinsic-conversions.html). When the user see a convert_to<X>(y) the conversion can also be anywhere.
Vicente Botet Escriba
The problem with implicit conversion is not related to the fact the conversion is a non-member function, but to the fact it is implicit. C++0x has added explicit conversion operator to solve this issue. Of course the non-member conversion operator overloading could also be explicit, so no problem with unwanted implicit conversions.
Vicente Botet Escriba
OK, not harder but computationally more expensive. Imagine a simple call such as `T t; U u; f( t, u );` If there are a number of overloads of `f()` but none are an exactly match the number of conversion possibilities could become large much more rapidly with free-function conversion operators.
Charles Bailey
Yes, the non-member functions may be defined anywhere, but there is the limiting factor that their name is known at the point of call. Because conversion operators may be invoked implicitly in lines of code that don't directly reference the name of either the source or destination type it's one more unknown to cope with.
Charles Bailey
It *could* be explicit, but surely if you are going to have free-function conversion functions you would want to allow for them to be implicit as well otherwise why not just use a named function?
Charles Bailey
The complexity of this problem depends on the number of conversion not on whether the conversion is defined by a non-member function. In the other side the possibility to define conversions with non-member function allows to increase the number of conversion without modifying the concerned classes.
Vicente Botet Escriba
Having a named function let the open door to have different names. Having a common mechanism allows to write generic code.
Vicente Botet Escriba
+1 I have accepted the answer. The comments were very useful.
Vicente Botet Escriba
+1  A: 

If there's no direct relation between Source and Destination, then I want to explicitly identify conversions between them, as with a Source sourceFromDestination(const Destination&) function, and not be surprised by random implicit conversions.

Bill
This is not an answer as your justification is subjective.
Vicente Botet Escriba