3

Chapter 4.11.3 of the book C++ Primer says the following:

A named cast has the following form: cast-name<type>(expression); where type is the target type of the conversion, and expression is the value to be cast. If type is a reference, then the result is an lvalue.

Can anyone give an example of this? Is conversion to a reference even possible?

L.S. Roth
  • 447
  • 2
  • 14
  • [This question about reference collapsing](https://stackoverflow.com/questions/13725747/concise-explanation-of-reference-collapsing-rules-requested-1-a-a-2) might be helpful. – Some programmer dude Jul 12 '20 at 13:40
  • Cast to a reference (from an instance/reference) is very similar to cast to a pointer (from a pointer). Main difference is that `dynamic_cast` return nullptr for pointers but thrown an exception for reference if it cannot convert to the target type. – Phil1970 Jul 12 '20 at 15:57

3 Answers3

3

Is conversion to a reference even possible?

Yes, depending on the object you begin with. Most simple example is one lvalue reference converted to another. This can even be an added cv-qualifier (or removed, with const_cast), such as:

int const & foo(int & i) {
    return static_cast<int const &>(i);
}

the derived-to-base casts and base-to-derived (dynamic) casts mentioned in the other answers are other such examples.

A more interesting example is the std::reference_wrapper, which is an object you can receive as an rvalue, and cast it to an lvalue reference of the contained type:

int & foo(std::reference_wrapper<int> i) {
    return static_cast<int &>(i);
}

Note that the cast above happens implicitly (I could've used return i), but in some contexts (e.g. capturing variables with auto type) you might want to write the cast explicitly.

What is meant in C++ Primer is simply that the behavior of casts in these examples, and others, is basically what you would expect - the result of a cast to a reference type is an lvalue.

Benny K
  • 868
  • 6
  • 18
0

Here is a short example with a class hierarchy. In main you find code that constructs a Derived object on the heap and stores the pointer to it in p. If you want to work with pointers, you can just dynamic_cast<Derived*> that pointer. But sometimes like in function work you have a reference to the base class. If inside the function you know at some place that the object b is of type Derived (maybe you checked an enum member giving you the type or based on some other information you know that it must be some special type), then can directly cast from reference Base& to reference Derived&. In that special case of dynamic_cast it also makes a difference because casting a pointer will return nullptr if the cast is not possible, but casting a reference will throw an exception if the cast is not possible.

#include <memory>

struct Base {
    virtual ~Base() = default;
};
struct Derived : Base {
    void f() const noexcept {}
};

void work(const Base& b) noexcept
{
    // Check what to do, then assume it must be a Derived, then work on it:
    dynamic_cast<const Derived&>(b).f();
}

int main() {
    std::unique_ptr<Base> p{ std::make_unique<Derived>() };
    dynamic_cast<Derived*>(p.get())->f();
    work(*p);

    return 0;
}
Werner Henze
  • 16,404
  • 12
  • 44
  • 69
0

Example when type is not a reference: If i is a variable of type int, then static_cast<long int>(i) returns a non-lvalue of type long int.

Example when type is a reference: static_cast<Base&>(objectOfDerivedType) returns an lvalue of type reference-to-Base.

cs-
  • 435
  • 3
  • 9