Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the C++ specification say how types are chosen in the static_cast/const_cast chain to be used in a C-style cast?

This question concerns something I noticed in the C++ spec when I was trying to answer this earlier, intriguing question about C-style casts and type conversions.

The C++ spec talks about C-style casts in §5.4. It says that the cast notation will try the following casts, in this order, until one is found that is valid:

  • const_cast
  • static_cast
  • static_cast followed by const_cast
  • reinterpret_cast
  • reinterpret_cast followed by const_cast.

While I have a great intuitive idea of what it means to use a static_cast followed by a const_cast (for example, to convert a const Derived* to a Base* by going through a const_cast<Base*>(static_cast<const Base*>(expr))), I don't see any wording in the spec saying how, specifically, the types used in the static_cast/const_cast series are to be deduced. In the case of simple pointers it's not that hard, but as seen in the linked question the cast might succeed if an extra const is introduced in one place and removed in another.

Are there any rules governing how a compiler is supposed to determine what types to use in the casting chain? If so, where are they? If not, is this a defect in the language, or are there sufficient implicit rules to uniquely determine all the possible casts to try?

like image 446
templatetypedef Avatar asked Aug 29 '16 22:08

templatetypedef


People also ask

What is a C-style cast?

C-style casts can be used to convert any type into any other type, potentially with unsafe results (such as casting an integer into a pointer type). (<type>)<value> This example casts an int to a double for the purpose of avoiding truncation due to integer division: double result = (double)4/5; Popular pages.

Can I use static_cast in C?

Static casts are only available in C++.

Why is static_cast better than C-style cast?

In short: static_cast<>() gives you a compile time checking ability, C-Style cast doesn't. static_cast<>() is more readable and can be spotted easily anywhere inside a C++ source code, C_Style cast is'nt. Intentions are conveyed much better using C++ casts.

What is casting in C++?

A cast is a special operator that forces one data type to be converted into another. As an operator, a cast is unary and has the same precedence as any other unary operator. The most general cast supported by most of the C++ compilers is as follows − (type) expression. Where type is the desired data type.

What is the difference between static_cast and casting in C++?

The casting conversion is the general thing of the programming language because it converts from one type into another data type. Likewise, static_cast is the operator and is used for done the casting operations in the compile timeWe already said that the casting is done for both implicit and explicit conversions.

How many types of casting are there in C++?

C++ supports four types of casting: 1 Static Cast 2 Dynamic Cast 3 Const Cast 4 Reinterpret Cast More ...

Can I use static_cast to cast down the hierarchy?

So, don’t use static_cast to cast down the hierarchy unless you’re absolutely sure the conversion is valid. static_cast won’t let you convert between two unrelated classes — dynamic_cast is related to static_cast in the sense it helps to cast through inheritance, but it’s more powerful than static_cast but has an overhead.

Does static_cast perform a tight type checking?

As we know static_cast performs a tight type checking, let’s the changed code slightly to see it: Try to compile the above code, What do you see?? Compilation Error!!!!!!!


1 Answers

If not, is this a defect in the language, or are there sufficient implicit rules to uniquely determine all the possible casts to try?

What about constructing all types that can be cast to the target type using only const_cast, i.e. all "intermediate types"?

Given target type T, if static_cast doesn't work, identify all positions where one could add cv-qualifiers such that the resulting type can be cast back to T by const_cast1. Sketch of the algorithm: take the cv-decomposition ([conv.qual]/1) of T; each cvj can be augmented. If T is a reference, we can augment the referee type's cv-qualification.

Now add const volatile to all these places. Call the resulting type CT. Try static_casting the expression to CT instead. If that works, our cast chain is const_cast<T>(static_cast<CT>(e)).

If this doesn't work, there very probably is no conversion using static_cast followed by const_cast (I haven't delved into the deep corners of overload resolution (well I have, but not for this question)). But we could use brute force to repeatedly remove const/volatiles and check each type if we really wanted. So in theory, there is no ambiguity or underspecification; if there is some cast chain, it can be determined. In practice, the algorithm can be made very simple, because the "most cv-qualified" type we can construct from T is (assuredly) sufficient.

like image 171
Columbo Avatar answered Sep 21 '22 18:09

Columbo