What exactly is or was the purpose of C++ function-style casts?
I am talking about "type(value)"-style casts. The books I have read pass over them quickly, saying only that they are semantically equivalent to C-style casts, "(type) value", and that they should be avoided. If they mean the same thing an old-style cast does, why were they ever added to the language? Also, because declarations can contain superfluous parentheses, this code: "T x(T(y));" doesn't do what someone intending to use the function-style casts would expect; it declares a function named x accepting a T and returning a T rather than constructing a T variable named x by casting y to a T.
Were they a mistake in the design of the language?
Solution 1:
Function style casts bring consistency to primitive and user defined types. This is very useful when defining templates. For example, take this very silly example:
template<typename T, typename U>
T silly_cast(U const &u) {
return T(u);
}
My silly_cast
function will work for primitive types, because it's a function-style cast. It will also work for user defined types, so long as class T has a single argument constructor that takes a U or U const &.
template<typename T, typename U>
T silly_cast(U const &u) {
return T(u);
}
class Foo {};
class Bar {
public:
Bar(Foo const&) {};
};
int main() {
long lg = 1L;
Foo f;
int v = silly_cast<int>(lg);
Bar b = silly_cast<Bar>(f);
}
Solution 2:
The purpose of them is so you could pass more than one argument to a class' constructor:
T(a1, a2); // call 2-argument constructor
(T)(a1, a2); // would only pass a2.
There is no mechanism that the (T) expr
style cast would be able to pass multiple arguments, so a new form of conversion was needed. It's natural to define (T) expr
as a degenerate case of T(expr)
.
Contrary to what some people here say, (T) expr
works exactly like T(expr)
, so it will work just fine with class types too.
Solution 3:
It is somewhat easier to parse the function-style casts in a language where parentheses are already heavily (over-)used.
Were they a mistake? Possibly - but only to the extent that they were unable to completely supersede the C-style casts, and therefore provided a Perl-like "there's more than one way to do it" mechanism for casting. With the explicit and distinctive modern casts:
dynamic_cast<type>(value);
reinterpret_cast<type>(value);
static_cast<type>(value);
const_cast<type>(value);
there is no reason to use the C-style casts any more, and less reason to use function-style casts.
Solution 4:
C-style casts should not be used.
Function-style casts should be used, especially when the target type is a class name (or class template specialization). They fit the pattern of apparent constructor calls in the case with one argument.
MyClass( expr ); // Creates temporary, initialized like MyClass obj( expr );
MyClass( e1, e2 ); // Similar, and no other way to write this.
int( expr ); // Function-style cast.
Solution 5:
AFAIK function-style casts are an extension to native types of the usual syntax of temporary creation for classes: as long as you can create a temporary object inside an expression using the syntax ClassName(parameters)
, there's no reason why you shouldn't do that with native types. edit Notice that, as @steve said, this is very useful in templates
Notice that one-parameter constructors in C++ are often somehow "felt" as conversion facilities, see for example the syntax (conversion constructor) that allows you to initialize a new object using an equal sign followed by a value
ClassName MyObject = 3;
which actually means
ClassName MyObject(3);
and (presumably) calls the one-int
-parameter constructor of ClassName.
By the way, here's a nice page about function-style casts.