What is a complete list of the kinds of automatic conversions the C ++ compiler will perform on a function argument?

If a C ++ function f (X x) is given, where x is a variable of type X and a variable y of type Y, then what are all the automatic / implicit conversions that the C ++ compiler will perform on y, so the expression "f (y) ; " is legal code (no errors, no warnings)?

For example:

Pass Derived & to work using Base & - OK Pass Base & for function Derived & - not ok without throwing Passing int to work with long - ok, creates a temporary long Pass int & to do long & - NOT OK, referring to temporary

Note that built-in types have some quirks when compared to classes: Derived can be passed to a function using Base (although it is sliced), and int can be passed to a function that takes a long time, but you cannot pass int & to a function that takes a long & !!

What's the complete list of cases that are always "good" (you don't need to use any cast to do this)?

For what: I have a C ++ script-binding library that allows you to bundle your C ++ code and it will call C ++ functions at runtime based on script expressions. Because expressions are evaluated at run time, any legal combinations of source types and function argument types that might be required to be used in an expression must be anticipated and precompiled in the library before they can be used at run time. If I omit the legal combination, some sensible expressions will not work in runtime expressions; if I accidentally create a combination that is not legal C ++, my library simply won't compile.

Edit (narrowing down the question):

Thanks, all of your answers are actually very helpful. I knew the answer was complex, but it looks like I only saw the tip of the iceberg.

Let me rephrase the question a bit to further narrow it down: I'll let the user specify a BaseClasses list and a UserDefinedConversions list. For the databases, I'll create everything including references and pointer transformations. But what cases (const / reference / pointer) can be safely done from the UserDefined Conversions list? (The user will give a bare type, I'll decorate with *, &, const, etc. in the template.)

+2


source to share


3 answers


Note how built-in types have some quirks compared to classes: a Derivatives can be passed to a function that takes a Base (although it is sliced), and an int can be passed to a function that takes a long time, but you cannot pass int & to a function that takes a long & !!

This is not a quirk of built-in types vs. class. This is a quirk of inheritance.

If you had classes A and B and B had a conversion to (either because A has a constructor that takes B, or because B has a conversion operator in A), then they will behave the same as int and long in is a conversion can occur when the function takes on a value, but not where a non-const reference is required. In both cases, the problem is that there is no object to which the required non-const reference can be taken: long & cannot refer to int, and A & cannot refer to B, and no non-const reference can refer to a temporary one.



The reason the base / derived example does not meet this issue is because a non-const base reference can refer to a derived object. The fact that the types are user-defined is necessary, but not sufficient, for the reference to be legal. Convertible custom classes where there is no inheritance behave the same as built-in classes.

This comment is too long for comments, so I used the answer. It doesn't really answer your question, other than to distinguish between:

  • "Transforms", where a reference to a derived class is passed to a function that references the base class.
  • Conversions where a custom or inline conversion actually creates an object, such as int to long.
+3


source


The C ++ Standard answers your question in 13.3.3.1 Implicit Conversion Sequences , but it is too large to post here. I recommend that you read at least that part of the C ++ standard.



Hope this link will help you.

+5


source


Unfortunately, the answer to your question is extremely difficult, taking up at least 9 pages of the ISO C ++ standard (in particular: ~ 6 pages in "Standard Conversions" and ~ 3 pages in "13.3.3.1 Implicit Conversion Sequences").

Brief summary: A transformation that does not require casting is called an "implicit transformation sequence". C ++ has "standard conversions", which are conversions between basic types (eg char

promoted to int

), and things like matrix-pointer decomposition; there may be several of them in a row, hence the term "sequences". C ++ also allows custom conversions, which are defined by conversion functions and constructor conversions. It is important to note that an implicit conversion sequence can have at most one custom conversion, with an optional sequence of standard conversions on both sides - C ++ will never "cling" to more than one user - a specific conversion together without translation.

(If anyone would like to post this post with full details, please go ahead ... But for me it will just be grueling, sorry: - /)

+4


source







All Articles