In Stroustrup's C++ Programming Language book (3rd edition), in the Numerics chapter he shows the following code snippet:
void f(valarray<double>& d) { slice_array<double>& v_even = d[slice(0,d.size()/2,2)]; slice_array<double>& v_odd = d[slice(1,d.size()/2,2)]; v_odd *= v_even; v_even = 0; }
The problem is, v_even
and v_odd
are non-const references to temporaries, which isn't allowed. And attempting to compile this emits an error:
error: non-const lvalue reference to type 'slice_array<double>' cannot bind to a temporary of type 'slice_array<double>' slice_array<double>& v_even = d[slice(0,d.size()/2,2)]; ^ ~~~~~~~~~~~~~~~~~~~~~~~~
I checked through all of the errata available online and there's nothing that touches upon this fundamental problem. Am I missing something? Did the language change in this regard since the book was printed (unlikely, since the book itself mentions the rule against non-const references to temporaries)? What's going on here?
If I modify the function to use values instead of references, e.g. slice_array<double> v_even = ...
, then this actually compiles. However, it turns out my local C++ headers make the copy constructor public, whereas Stroustrup and various online references (cppreference.com, cplusplus.com) claim the copy constructor is private. I assume that means this solution is non-portable. This is reinforced by the fact that Stroustrup explicitly lists a code sample with non-reference variables and says this produces an error.
The C++98 spec (PDF) declares slice_array<T>
as having a private copy constructor. By 2005 (according to this spec), and presumably as part of C++03, this changed to a public copy constructor.
No. A reference is simply an alias for an existing object.
Whether a reference refers to a const or nonconst type affects what we can do with that reference, not whether we can alter the binding of the reference itself." I think this means that making a reference a "const" when it is referenced to a non const object does absolutely nothing.
There seem to be a couple of different issues with the original code sample, and also the declarations given in the book for a number of operators.
The 'best' solution I believe is to do as follows
void f(valarray<double>& d) { const slice_array<double>& v_even = d[slice(0,d.size()/2,2)]; const slice_array<double>& v_odd = d[slice(1,d.size()/2,2)]; v_odd *= v_even; v_even = 0; }
All operators on slice_array<T>
are defined as const
as they are not modifying the slice itself, but the contents. These are defined incorrectly in the book as non-const
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With