What exactly is or was the purpose of C++ function-style casts?

19,691

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.

Share:
19,691
Admin
Author by

Admin

Updated on June 03, 2022

Comments

  • Admin
    Admin almost 2 years

    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?