Changes to Conversion Operators
The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.
The latest version of this topic can be found at Changes to Conversion Operators.
The syntax for conversion operators has changed from Managed Extensions for C++ to Visual C++.
One example is to write op_Implicit
to specify a conversion. Here is a definition of MyDouble
taken from the language specification:
__gc struct MyDouble {
static MyDouble* op_Implicit( int i );
static int op_Explicit( MyDouble* val );
static String* op_Explicit( MyDouble* val );
};
This says that, given an integer, the algorithm for converting that integer into a MyDouble
is provided by the op_Implicit
operator. Moreover, that conversion will be performed implicitly by the compiler. Similarly, given a MyDouble
object, the two op_Explicit
operators provide the respective algorithms for converting that object into either an integer or a managed String
entity. However, the compiler will not perform the conversion unless explicitly requested by the user.
In C#, this looks as follows:
class MyDouble {
public static implicit operator MyDouble( int i );
public static explicit operator int( MyDouble val );
public static explicit operator string( MyDouble val );
};
The C# code looks more like C++ than Managed Extensions for C++ does. That is not the case in the new syntax.
The ISO-C++ committee introduced a keyword, explicit
, to mitigate unintended consequences – for example, an Array
class which takes a single integer argument as a dimension will implicitly convert any integer into an Array
object which is not what you want. One way to prevent this is a design idiom of a dummy second argument to a constructor
On the other hand, you should not provide a conversion pair when designing a class type within C++. The best example for that is the standard string class. The implicit conversion is the single-argument constructor taking a C-style string. However, it does not provide the corresponding implicit conversion operator – that of converting a string object to a C-style string, but rather requires the user to explicitly invoke a named function – in this case, c_str()
.
So, associating an implicit/explicit behavior on a conversion operator (and as encapsulating the set of conversions to a single form of declaration) appears to be an improvement on the original C++ support for conversion operators, which eventually led to the explicit
keyword. The Visual C++ language support for conversion operators looks as follows, which is slightly less verbose than that of C# because of the default behavior of the operator supporting an implicit application of the conversion algorithm:
ref struct MyDouble {
public:
static operator MyDouble^ ( int i );
static explicit operator int ( MyDouble^ val );
static explicit operator String^ ( MyDouble^ val );
};
Another change is that a single argument constructor is treated as if it is declared as explicit
. This means that in order to trigger its invocations, an explicit cast is required. Note, however, that if an explicit conversion operator is defined, it and not the single-argument constructor, is invoked.