2

(I know this is very similar to some other questions on here, but I haven't found any that specifically, language-lawyerly, answer this precise detail. Most of the near-duplicates are just asking whether they should use static_cast over functional-style casts (answer: yes), or the difference between static_cast and C-style casts.)

In C++, the following two casts appear to be very similar:

template<class T, class U> auto convert1(U&& u) {
    return T( std::forward<U>(u) );
}

template<class T, class U> auto convert2(U&& u) {
    return static_cast<T>( std::forward<U>(u) );
}

Is there any difference for any types T, U; or are they 100% identical in effect?

If they are different, I'd appreciate some examples of places in the Standard Library where the subtle difference is relevant. (I mean like how std::make_shared<T>(args...) is specified to construct its object with T(args...) instead of T{args...} because of the subtle difference between T() and T{} there.)

Quuxplusone
  • 23,928
  • 8
  • 94
  • 159
  • P.S.: no need to comment that `T(u,v)` works and `static_cast(u,v)` doesn't. I'm asking about a single argument `u` only. :) – Quuxplusone Aug 14 '17 at 19:36
  • Technically, T(std::forward(u)) is a call to a constructor, not a cast. – Michaël Roy Aug 14 '17 at 19:43
  • @Justin: At least the top-voted answer there mentions functional-style casts, but unfortunately it doesn't say anything about their semantics; it just says "they exist" and moves on. The *questioner* over there didn't care about functional-style casts. – Quuxplusone Aug 14 '17 at 19:43
  • You may enjoy reading this: https://isocpp.org/wiki/faq/style-and-techniques#static-cast – Jesper Juhl Aug 14 '17 at 19:44
  • 1
    @Quuxplusone "The questioner over there didn't care about functional-style casts." False. Did you even read that question? On the bullet point list are C-style casts *and* function-style casts – Justin Aug 14 '17 at 19:44
  • @Quuxplusone Also, the top voted answer there implies, but didn't explicitly say, that function-style casts are equivalent to C-style casts. It's pretty clear that that was meant. – Justin Aug 14 '17 at 19:45
  • @JesperJuhl: https://isocpp.org/wiki/faq/style-and-techniques#static-cast talks specifically about `static_cast` versus C-style casts. FWIW, obviously I agree with their style recommendations in this area. I'm just asking the language-lawyer question here. – Quuxplusone Aug 14 '17 at 19:46
  • 1
    @Quuxplusone and *I* was just passing by and posting a comment with a somewhat relevant link I thought you might enjoy reading :) – Jesper Juhl Aug 14 '17 at 19:48

1 Answers1

7

The functional-style cast notation T(x) for a single argument is defined by the standard to be identical to the C-style cast notation (T)x. The C-style cast notation can do any conversion that static_cast can do, and others (which may be undesired), such as casting away constness. So for example convert1 could be used to convert int const* to int* while convert2 could not.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • Ah, yes. [expr.type.conv] "If the initializer is a parenthesized single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression." That seems pretty definite. Thanks! – Quuxplusone Aug 14 '17 at 19:49
  • "and others" also includes `reinterpret_cast` which would certainly not be desired – M.M Aug 14 '17 at 21:17
  • 2
    I had not realised this before. It's horrifying. I am now concerned that any constructor I have ever written in the form `auto x = Y(z)` is a time-bomb. – Richard Hodges Aug 15 '17 at 06:08